blob: b0767fb4ea3640a34e14f29a4faff577fdb4b173 [file] [log] [blame]
Austin Schuhc8ca2442013-02-23 12:29:33 -08001#!/usr/bin/python
2
Austin Schuh3c542312013-02-24 01:53:50 -08003import control_loop
Austin Schuh0d9467a2014-02-15 22:36:45 -08004import controls
Austin Schuhc8ca2442013-02-23 12:29:33 -08005import numpy
Austin Schuhc8ca2442013-02-23 12:29:33 -08006import sys
Austin Schuhc8ca2442013-02-23 12:29:33 -08007from matplotlib import pylab
Austin Schuhc8ca2442013-02-23 12:29:33 -08008
Austin Schuh3bb9a442014-02-02 16:01:45 -08009class Claw(control_loop.ControlLoop):
10 def __init__(self, name="RawClaw"):
11 super(Claw, self).__init__(name)
Austin Schuhc8ca2442013-02-23 12:29:33 -080012 # Stall Torque in N m
James Kuszmaule1755b32014-02-13 06:27:48 -080013 self.stall_torque = 2.42
Austin Schuhc8ca2442013-02-23 12:29:33 -080014 # Stall Current in Amps
James Kuszmaule1755b32014-02-13 06:27:48 -080015 self.stall_current = 133
James Kuszmaul92797402014-02-17 14:08:49 -080016 # Free Speed in RPM
17 self.free_speed = 5500.0
Austin Schuh3c542312013-02-24 01:53:50 -080018 # Free Current in Amps
James Kuszmaule1755b32014-02-13 06:27:48 -080019 self.free_current = 2.7
Austin Schuh3bb9a442014-02-02 16:01:45 -080020 # Moment of inertia of the claw in kg m^2
James Kuszmaul92797402014-02-17 14:08:49 -080021 # measured from CAD
22 self.J_top = 0.3
23 self.J_bottom = 0.9
Austin Schuhc8ca2442013-02-23 12:29:33 -080024 # Resistance of the motor
James Kuszmaul92797402014-02-17 14:08:49 -080025 self.R = 12.0 / self.stall_current
Austin Schuhc8ca2442013-02-23 12:29:33 -080026 # Motor velocity constant
Austin Schuh3c542312013-02-24 01:53:50 -080027 self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
28 (13.5 - self.R * self.free_current))
Austin Schuhc8ca2442013-02-23 12:29:33 -080029 # Torque constant
30 self.Kt = self.stall_torque / self.stall_current
31 # Gear ratio
James Kuszmaule1755b32014-02-13 06:27:48 -080032 self.G = 14.0 / 48.0 * 18.0 / 32.0 * 18.0 / 66.0 * 12.0 / 60.0
Austin Schuhc8ca2442013-02-23 12:29:33 -080033 # Control loop time step
34 self.dt = 0.01
35
James Kuszmaule2afbe42014-02-17 22:29:59 -080036 # State is [bottom position, bottom velocity, top - bottom position,
37 # top - bottom velocity]
38 # Input is [bottom power, top power - bottom power * J_top / J_bottom]
James Kuszmaul92797402014-02-17 14:08:49 -080039 # Motor time constants. difference_bottom refers to the constant for how the
40 # bottom velocity affects the difference of the top and bottom velocities.
41 self.common_motor_constant = -self.Kt / self.Kv / (self.G * self.G * self.R)
42 self.bottom_bottom = self.common_motor_constant / self.J_bottom
James Kuszmaulc02a39a2014-02-18 15:45:16 -080043 self.difference_bottom = -self.common_motor_constant * (1 / self.J_bottom
James Kuszmaul92797402014-02-17 14:08:49 -080044 - 1 / self.J_top)
45 self.difference_difference = self.common_motor_constant / self.J_top
Austin Schuhc8ca2442013-02-23 12:29:33 -080046 # State feedback matrices
James Kuszmaule2afbe42014-02-17 22:29:59 -080047
Austin Schuhc8ca2442013-02-23 12:29:33 -080048 self.A_continuous = numpy.matrix(
James Kuszmaulc02a39a2014-02-18 15:45:16 -080049 [[0, 0, 1, 0],
50 [0, 0, 0, 1],
James Kuszmaul92797402014-02-17 14:08:49 -080051 [0, 0, self.bottom_bottom, 0],
52 [0, 0, self.difference_bottom, self.difference_difference]])
Austin Schuh0d9467a2014-02-15 22:36:45 -080053
James Kuszmaule2afbe42014-02-17 22:29:59 -080054 self.A_bottom_cont = numpy.matrix(
55 [[0, 1],
56 [0, self.bottom_bottom]])
57
58 self.A_diff_cont = numpy.matrix(
59 [[0, 1],
60 [0, self.difference_difference]])
61
James Kuszmaulc02a39a2014-02-18 15:45:16 -080062 # self.A_continuous[0:2, 0:2] = self.A_bottom_cont
63 # self.A_continuous[2:4, 2:4] = self.A_diff_cont
64 # self.A_continuous[3, 1] = self.difference_bottom
James Kuszmaule2afbe42014-02-17 22:29:59 -080065
James Kuszmaul92797402014-02-17 14:08:49 -080066 self.motor_feedforward = self.Kt / (self.G * self.R)
James Kuszmaulf2ed6e62014-02-17 17:52:07 -080067 self.motor_feedforward_bottom = self.motor_feedforward / self.J_bottom
68 self.motor_feedforward_difference = self.motor_feedforward / self.J_top
James Kuszmaul92797402014-02-17 14:08:49 -080069 self.motor_feedforward_difference_bottom = (
70 self.motor_feedforward * (1 / self.J_bottom - 1 / self.J_top))
Austin Schuhc8ca2442013-02-23 12:29:33 -080071 self.B_continuous = numpy.matrix(
Austin Schuh0d9467a2014-02-15 22:36:45 -080072 [[0, 0],
James Kuszmaule2afbe42014-02-17 22:29:59 -080073 [0, 0],
James Kuszmaulc02a39a2014-02-18 15:45:16 -080074 [self.motor_feedforward_bottom, 0],
75 [-self.motor_feedforward_bottom,
James Kuszmaul92797402014-02-17 14:08:49 -080076 self.motor_feedforward_difference]])
James Kuszmaule2afbe42014-02-17 22:29:59 -080077
James Kuszmaulc02a39a2014-02-18 15:45:16 -080078 print "Cont X_ss", self.motor_feedforward / -self.common_motor_constant
79
James Kuszmaule2afbe42014-02-17 22:29:59 -080080 self.B_bottom_cont = numpy.matrix(
81 [[0],
82 [self.motor_feedforward_bottom]])
83
84 self.B_diff_cont = numpy.matrix(
85 [[0],
86 [self.motor_feedforward_difference]])
87
Austin Schuh0d9467a2014-02-15 22:36:45 -080088 self.C = numpy.matrix([[1, 0, 0, 0],
James Kuszmaulc02a39a2014-02-18 15:45:16 -080089 [1, 1, 0, 0]])
Austin Schuh0d9467a2014-02-15 22:36:45 -080090 self.D = numpy.matrix([[0, 0],
91 [0, 0]])
Austin Schuhc8ca2442013-02-23 12:29:33 -080092
Austin Schuhc1f68892013-03-16 17:06:27 -070093 self.A, self.B = self.ContinuousToDiscrete(
94 self.A_continuous, self.B_continuous, self.dt)
Austin Schuhc8ca2442013-02-23 12:29:33 -080095
James Kuszmaule2afbe42014-02-17 22:29:59 -080096 self.A_bottom, self.B_bottom = controls.c2d(
97 self.A_bottom_cont, self.B_bottom_cont, self.dt)
98 self.A_diff, self.B_diff = controls.c2d(
99 self.A_diff_cont, self.B_diff_cont, self.dt)
100
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800101 print "A"
102 print self.A
103 print "B"
104 print self.B
James Kuszmaule2afbe42014-02-17 22:29:59 -0800105
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800106 X_ss = numpy.matrix([[0], [0], [0.0], [0]])
107
108 U = numpy.matrix([[1.0],[1.0]])
109 A = self.A
110 B = self.B
111 #X_ss[2, 0] = X_ss[2, 0] * A[2, 2] + B[2, 0] * U[0, 0]
112 X_ss[2, 0] = 1 / (1 - A[2, 2]) * B[2, 0] * U[0, 0]
113 #X_ss[3, 0] = X_ss[3, 0] * A[3, 3] + X_ss[2, 0] * A[3, 2] + B[3, 0] * U[0, 0] + B[3, 1] * U[1, 0]
114 #X_ss[3, 0] * (1 - A[3, 3]) = X_ss[2, 0] * A[3, 2] + B[3, 0] * U[0, 0] + B[3, 1] * U[1, 0]
115 X_ss[3, 0] = 1 / (1 - A[3, 3]) * (X_ss[2, 0] * A[3, 2] + B[3, 1] * U[1, 0] + B[3, 0] * U[0, 0])
116 #X_ss[3, 0] = 1 / (1 - A[3, 3]) / (1 - A[2, 2]) * B[2, 0] * U[0, 0] * A[3, 2] + B[3, 0] * U[0, 0] + B[3, 1] * U[1, 0]
117 X_ss[0, 0] = A[0, 2] * X_ss[2, 0] + B[0, 0] * U[0, 0]
118 X_ss[1, 0] = A[1, 2] * X_ss[2, 0] + A[1, 3] * X_ss[3, 0] + B[1, 0] * U[0, 0] + B[1, 1] * U[1, 0]
119
120 print "X_ss", X_ss
121
Austin Schuh0d9467a2014-02-15 22:36:45 -0800122 #controlability = controls.ctrb(self.A, self.B);
123 #print "Rank of controlability matrix.", numpy.linalg.matrix_rank(controlability)
124
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800125 self.Q = numpy.matrix([[(1.0 / (0.40 ** 2.0)), 0.0, 0.0, 0.0],
126 [0.0, (1.0 / (0.007 ** 2.0)), 0.0, 0.0],
Austin Schuhcda86af2014-02-16 16:16:39 -0800127 [0.0, 0.0, 0.2, 0.0],
128 [0.0, 0.0, 0.0, 2.00]])
129
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800130 self.R = numpy.matrix([[(1.0 / (40.0 ** 2.0)), 0.0],
131 [0.0, (1.0 / (5.0 ** 2.0))]])
James Kuszmaule2afbe42014-02-17 22:29:59 -0800132 #self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
133
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800134 self.K = numpy.matrix([[50, 0.0, 1, 0.0],
135 [0.0, 300, 0.0, 1.1]])
136 lstsq_A = numpy.identity(2)
137 lstsq_A[0] = self.B[1]
138 lstsq_A[1] = self.B[3]
139 print "System of Equations coefficients:"
140 print lstsq_A
141 print "det", numpy.linalg.det(lstsq_A)
142 self.K[1, 0] = -lstsq_A[0, 0] * self.K[0, 0] / lstsq_A[0, 1]
James Kuszmaule2afbe42014-02-17 22:29:59 -0800143 #self.K[0:2, 0] = numpy.linalg.lstsq(lstsq_A, numpy.matrix([[0.0], [0.0]]))[0]
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800144 out_x = numpy.linalg.lstsq(
145 lstsq_A,
146 numpy.matrix([[self.A[1, 2]], [self.A[3, 2]]]))[0]
147 self.K[1, 2] = -lstsq_A[0, 0] * (self.K[0, 2] - out_x[0]) / lstsq_A[0, 1] + out_x[1]
Austin Schuhcda86af2014-02-16 16:16:39 -0800148
149 print "K unaugmented"
150 print self.K
James Kuszmaule2afbe42014-02-17 22:29:59 -0800151 print "B * K unaugmented"
152 print self.B * self.K
153 F = self.A - self.B * self.K
James Kuszmaule2afbe42014-02-17 22:29:59 -0800154 print "A - B * K unaugmented"
155 print F
156 print "eigenvalues"
157 print numpy.linalg.eig(F)[0]
Austin Schuhc8ca2442013-02-23 12:29:33 -0800158
159 self.rpl = .05
160 self.ipl = 0.008
Austin Schuh3c542312013-02-24 01:53:50 -0800161 self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
Austin Schuh0d9467a2014-02-15 22:36:45 -0800162 self.rpl + 1j * self.ipl,
James Kuszmaule2afbe42014-02-17 22:29:59 -0800163 self.rpl - 1j * self.ipl,
Austin Schuh3c542312013-02-24 01:53:50 -0800164 self.rpl - 1j * self.ipl])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800165
James Kuszmaul92797402014-02-17 14:08:49 -0800166 # The box formed by U_min and U_max must encompass all possible values,
167 # or else Austin's code gets angry.
Austin Schuhcda86af2014-02-16 16:16:39 -0800168 self.U_max = numpy.matrix([[12.0], [24.0]])
169 self.U_min = numpy.matrix([[-12.0], [-24.0]])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800170
Austin Schuhc1f68892013-03-16 17:06:27 -0700171 self.InitializeState()
172
173
Austin Schuh3bb9a442014-02-02 16:01:45 -0800174class ClawDeltaU(Claw):
175 def __init__(self, name="Claw"):
176 super(ClawDeltaU, self).__init__(name)
Austin Schuhc1f68892013-03-16 17:06:27 -0700177 A_unaugmented = self.A
178 B_unaugmented = self.B
Austin Schuh0d9467a2014-02-15 22:36:45 -0800179 C_unaugmented = self.C
Austin Schuhc1f68892013-03-16 17:06:27 -0700180
Austin Schuh0d9467a2014-02-15 22:36:45 -0800181 self.A = numpy.matrix([[0.0, 0.0, 0.0, 0.0, 0.0],
182 [0.0, 0.0, 0.0, 0.0, 0.0],
183 [0.0, 0.0, 0.0, 0.0, 0.0],
184 [0.0, 0.0, 0.0, 0.0, 0.0],
185 [0.0, 0.0, 0.0, 0.0, 1.0]])
186 self.A[0:4, 0:4] = A_unaugmented
187 self.A[0:4, 4] = B_unaugmented[0:4, 0]
Austin Schuhc1f68892013-03-16 17:06:27 -0700188
Austin Schuh0d9467a2014-02-15 22:36:45 -0800189 self.B = numpy.matrix([[0.0, 0.0],
190 [0.0, 0.0],
191 [0.0, 0.0],
192 [0.0, 0.0],
193 [1.0, 0.0]])
194 self.B[0:4, 1] = B_unaugmented[0:4, 1]
Austin Schuhc1f68892013-03-16 17:06:27 -0700195
Austin Schuh0d9467a2014-02-15 22:36:45 -0800196 self.C = numpy.concatenate((C_unaugmented, numpy.matrix([[0.0], [0.0]])),
197 axis=1)
198 self.D = numpy.matrix([[0.0, 0.0],
199 [0.0, 0.0]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700200
Austin Schuh0d9467a2014-02-15 22:36:45 -0800201 #self.PlaceControllerPoles([0.55, 0.35, 0.55, 0.35, 0.80])
202 self.Q = numpy.matrix([[(1.0 / (0.04 ** 2.0)), 0.0, 0.0, 0.0, 0.0],
203 [0.0, (1.0 / (0.01 ** 2)), 0.0, 0.0, 0.0],
204 [0.0, 0.0, 0.01, 0.0, 0.0],
205 [0.0, 0.0, 0.0, 0.08, 0.0],
206 [0.0, 0.0, 0.0, 0.0, (1.0 / (10.0 ** 2))]])
207
208 self.R = numpy.matrix([[0.000001, 0.0],
209 [0.0, 1.0 / (10.0 ** 2.0)]])
210 self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
211
212 self.K = numpy.matrix([[50.0, 0.0, 10.0, 0.0, 1.0],
213 [50.0, 0.0, 10.0, 0.0, 1.0]])
214 #self.K = numpy.matrix([[50.0, -100.0, 0, -10, 0],
215 # [50.0, 100.0, 0, 10, 0]])
216
217 controlability = controls.ctrb(self.A, self.B);
218 print "Rank of augmented controlability matrix.", numpy.linalg.matrix_rank(controlability)
Austin Schuhc1f68892013-03-16 17:06:27 -0700219
220 print "K"
221 print self.K
222 print "Placed controller poles are"
223 print numpy.linalg.eig(self.A - self.B * self.K)[0]
Austin Schuh0d9467a2014-02-15 22:36:45 -0800224 print [numpy.abs(x) for x in numpy.linalg.eig(self.A - self.B * self.K)[0]]
Austin Schuhc1f68892013-03-16 17:06:27 -0700225
226 self.rpl = .05
227 self.ipl = 0.008
Austin Schuh0d9467a2014-02-15 22:36:45 -0800228 self.PlaceObserverPoles([self.rpl + 1j * self.ipl, 0.10, 0.09,
Brian Silverman23a67ca2013-03-16 23:48:50 -0700229 self.rpl - 1j * self.ipl, 0.90])
Austin Schuh0d9467a2014-02-15 22:36:45 -0800230 #print "A is"
231 #print self.A
232 #print "L is"
233 #print self.L
234 #print "C is"
235 #print self.C
236 #print "A - LC is"
237 #print self.A - self.L * self.C
Austin Schuhc1f68892013-03-16 17:06:27 -0700238
Austin Schuh0d9467a2014-02-15 22:36:45 -0800239 #print "Placed observer poles are"
240 #print numpy.linalg.eig(self.A - self.L * self.C)[0]
241
242 self.U_max = numpy.matrix([[12.0], [12.0]])
243 self.U_min = numpy.matrix([[-12.0], [-12.0]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700244
245 self.InitializeState()
246
247
Austin Schuhcda86af2014-02-16 16:16:39 -0800248def FullSeparationPriority(claw, U):
249 bottom_u = U[0, 0]
250 top_u = U[1, 0] + bottom_u
251
252 #print "Bottom is", new_unclipped_bottom_u, "Top is", top_u
253 if bottom_u > claw.U_max[0, 0]:
254 #print "Bottom is too big. Was", new_unclipped_bottom_u, "changing top by", new_unclipped_bottom_u - claw.U_max[0, 0]
255 top_u -= bottom_u - claw.U_max[0, 0]
256 if top_u < claw.U_min[1, 0]:
257 top_u = claw.U_min[1, 0]
258
259 bottom_u = claw.U_max[0, 0]
260 if top_u > claw.U_max[1, 0]:
261 bottom_u -= top_u - claw.U_max[1, 0]
262 if bottom_u < claw.U_min[0, 0]:
263 bottom_u = claw.U_min[0, 0]
264
265 top_u = claw.U_max[1, 0]
266 if top_u < claw.U_min[1, 0]:
267 bottom_u -= top_u - claw.U_min[1, 0]
268 if bottom_u > claw.U_max[0, 0]:
269 bottom_u = claw.U_max[0, 0]
270
271 top_u = claw.U_min[1, 0]
272 if bottom_u < claw.U_min[0, 0]:
273 top_u -= bottom_u - claw.U_min[0, 0]
274 if top_u > claw.U_max[1, 0]:
275 top_u = claw.U_max[1, 0]
276
277 bottom_u = claw.U_min[0, 0]
278
279 return numpy.matrix([[bottom_u], [top_u - bottom_u]])
280
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800281def AverageUFix(claw, U, preserve_v3=False):
282 """Clips U as necessary.
Austin Schuhcda86af2014-02-16 16:16:39 -0800283
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800284 Args:
285 claw: claw object containing moments of inertia and U limits.
286 U: Input matrix to clip as necessary.
287 preserve_v3: There are two ways to attempt to clip the voltages:
288 -If you preserve the imaginary v3, then it will attempt to
289 preserve the effect on the separation of the two claws.
290 If it is not able to do this, then it calls itself with preserve_v3
291 set to False.
292 -If you preserve the ratio of the voltage of the bottom and the top,
293 then it will attempt to preserve the ratio of those two. This is
294 equivalent to preserving the ratio of v3 and the bottom voltage.
295 """
296 bottom_u = U[0, 0]
297 top_u = U[1, 0]
298 seperation_u = top_u - bottom_u * claw.J_top / claw.J_bottom
299
300 top_big = top_u > claw.U_max[0, 0]
301 top_small = top_u < claw.U_min[0, 0]
302 bot_big = bottom_u > claw.U_max[0, 0]
303 bot_small = top_u < claw.U_min[0, 0]
304 bottom_bad = bot_big or bot_small
305 top_bad = top_big or top_small
306 scalar = claw.U_max[0, 0] / max(numpy.abs(top_u), numpy.abs(bottom_u))
307 if bottom_bad and preserve_v3:
308 bottom_u *= scalar
309 top_u = seperation_u + bottom_u * claw.J_top / claw.J_bottom
310 if abs(top_u) > claw.U_max[0, 0]:
311 return AverageUFix(claw, U, preserve_v3=False)
312 elif top_bad and preserve_v3:
313 top_u *= scalar
314 bottom_u = (top_u - seperation_u) * claw.J_bottom / claw.J_top
315 if abs(bottom_u) > claw.U_max[0, 0]:
316 return AverageUFix(claw, U, preserve_v3=False)
317 elif (bottom_bad or top_bad) and not preserve_v3:
Austin Schuhcda86af2014-02-16 16:16:39 -0800318 top_u *= scalar
319 bottom_u *= scalar
320
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800321 return numpy.matrix([[bottom_u], [top_u]])
Austin Schuhcda86af2014-02-16 16:16:39 -0800322
Austin Schuh0d9467a2014-02-15 22:36:45 -0800323def ClipDeltaU(claw, U):
324 delta_u = U[0, 0]
325 top_u = U[1, 0]
326 old_bottom_u = claw.X[4, 0]
327
328 # TODO(austin): Preserve the difference between the top and bottom power.
329 new_unclipped_bottom_u = old_bottom_u + delta_u
330
331 #print "Bottom is", new_unclipped_bottom_u, "Top is", top_u
332 if new_unclipped_bottom_u > claw.U_max[0, 0]:
333 #print "Bottom is too big. Was", new_unclipped_bottom_u, "changing top by", new_unclipped_bottom_u - claw.U_max[0, 0]
334 top_u -= new_unclipped_bottom_u - claw.U_max[0, 0]
335 new_unclipped_bottom_u = claw.U_max[0, 0]
336 if top_u > claw.U_max[1, 0]:
337 new_unclipped_bottom_u -= top_u - claw.U_max[1, 0]
338 top_u = claw.U_max[1, 0]
339 if top_u < claw.U_min[1, 0]:
340 new_unclipped_bottom_u -= top_u - claw.U_min[1, 0]
341 top_u = claw.U_min[1, 0]
342 if new_unclipped_bottom_u < claw.U_min[0, 0]:
343 top_u -= new_unclipped_bottom_u - claw.U_min[0, 0]
344 new_unclipped_bottom_u = claw.U_min[0, 0]
345
346 new_bottom_u = numpy.clip(new_unclipped_bottom_u, claw.U_min[0, 0], claw.U_max[0, 0])
347 new_top_u = numpy.clip(top_u, claw.U_min[1, 0], claw.U_max[1, 0])
348
349 return numpy.matrix([[new_bottom_u - old_bottom_u], [new_top_u]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700350
Austin Schuhc8ca2442013-02-23 12:29:33 -0800351def main(argv):
Austin Schuh3c542312013-02-24 01:53:50 -0800352 # Simulate the response of the system to a step input.
Austin Schuh0d9467a2014-02-15 22:36:45 -0800353 #claw = ClawDeltaU()
354 #simulated_x = []
355 #for _ in xrange(100):
356 # claw.Update(numpy.matrix([[12.0]]))
357 # simulated_x.append(claw.X[0, 0])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800358
Austin Schuh0d9467a2014-02-15 22:36:45 -0800359 #pylab.plot(range(100), simulated_x)
360 #pylab.show()
Austin Schuhc8ca2442013-02-23 12:29:33 -0800361
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800362 # Simulate the closed loop response of the system.
Austin Schuhcda86af2014-02-16 16:16:39 -0800363 claw = Claw("TopClaw")
364 t = []
Austin Schuh0d9467a2014-02-15 22:36:45 -0800365 close_loop_x_bottom = []
366 close_loop_x_sep = []
James Kuszmaul4e4ec8e2014-02-18 10:46:49 -0800367 actual_sep = []
368 actual_x_bottom = []
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800369 close_loop_x_top = []
Austin Schuh0d9467a2014-02-15 22:36:45 -0800370 close_loop_u_bottom = []
371 close_loop_u_top = []
James Kuszmaul4e4ec8e2014-02-18 10:46:49 -0800372 R = numpy.matrix([[0.0], [0.00], [0.0], [0.0]])
373 claw.X[0, 0] = 1
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800374 claw.X[1, 0] = .0
375 claw.X_hat = claw.X
376 #X_actual = claw.X
Austin Schuhcda86af2014-02-16 16:16:39 -0800377 for i in xrange(100):
378 #print "Error is", (R - claw.X_hat)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800379 U = claw.K * (R - claw.X)
Austin Schuhcda86af2014-02-16 16:16:39 -0800380 #U = numpy.clip(claw.K * (R - claw.X_hat), claw.U_min, claw.U_max)
381 #U = FullSeparationPriority(claw, U)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800382 #U = AverageUFix(claw, U, preserve_v3=True)
Austin Schuhcda86af2014-02-16 16:16:39 -0800383 #U = claw.K * (R - claw.X_hat)
384 #U = ClipDeltaU(claw, U)
385 claw.UpdateObserver(U)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800386 claw.Update(U)
387 #X_actual = claw.A_actual * X_actual + claw.B_actual * U
388 #claw.Y = claw.C * X_actual
389 close_loop_x_bottom.append(claw.X[0, 0] * 10)
Austin Schuhcda86af2014-02-16 16:16:39 -0800390 close_loop_u_bottom.append(U[0, 0])
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800391 #actual_sep.append(X_actual[2, 0] * 100)
392 #actual_x_bottom.append(X_actual[0, 0] * 10)
393 close_loop_x_sep.append(claw.X[1, 0] * 100)
394 close_loop_x_top.append((claw.X[1, 0] + claw.X[0, 0]) * 10)
395 close_loop_u_top.append(U[1, 0])
Austin Schuhcda86af2014-02-16 16:16:39 -0800396 t.append(0.01 * i)
Austin Schuhc8ca2442013-02-23 12:29:33 -0800397
Austin Schuhcda86af2014-02-16 16:16:39 -0800398 pylab.plot(t, close_loop_x_bottom, label='x bottom')
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800399 pylab.plot(t, close_loop_x_sep, label='separation')
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800400 #pylab.plot(t, actual_x_bottom, label='true x bottom')
401 #pylab.plot(t, actual_sep, label='true separation')
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800402 pylab.plot(t, close_loop_x_top, label='x top')
Austin Schuhcda86af2014-02-16 16:16:39 -0800403 pylab.plot(t, close_loop_u_bottom, label='u bottom')
404 pylab.plot(t, close_loop_u_top, label='u top')
Austin Schuh0d9467a2014-02-15 22:36:45 -0800405 pylab.legend()
Austin Schuhfa033692013-02-24 01:00:55 -0800406 pylab.show()
Austin Schuhc8ca2442013-02-23 12:29:33 -0800407
Austin Schuh3c542312013-02-24 01:53:50 -0800408 # Write the generated constants out to a file.
Austin Schuhcda86af2014-02-16 16:16:39 -0800409 if len(argv) != 3:
410 print "Expected .h file name and .cc file name for the claw."
Austin Schuhc8ca2442013-02-23 12:29:33 -0800411 else:
Austin Schuhcda86af2014-02-16 16:16:39 -0800412 claw = Claw("Claw")
413 loop_writer = control_loop.ControlLoopWriter("Claw", [claw])
Austin Schuh683a0d02013-03-02 01:51:31 -0800414 if argv[1][-3:] == '.cc':
Austin Schuhcda86af2014-02-16 16:16:39 -0800415 loop_writer.Write(argv[2], argv[1])
Austin Schuh683a0d02013-03-02 01:51:31 -0800416 else:
Austin Schuhcda86af2014-02-16 16:16:39 -0800417 loop_writer.Write(argv[1], argv[2])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800418
419if __name__ == '__main__':
420 sys.exit(main(sys.argv))