blob: 7d616c6738e04f540b09d43e778313efc9a533a6 [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 Kuszmaul92797402014-02-17 14:08:49 -080062 self.motor_feedforward = self.Kt / (self.G * self.R)
James Kuszmaulf2ed6e62014-02-17 17:52:07 -080063 self.motor_feedforward_bottom = self.motor_feedforward / self.J_bottom
64 self.motor_feedforward_difference = self.motor_feedforward / self.J_top
James Kuszmaul92797402014-02-17 14:08:49 -080065 self.motor_feedforward_difference_bottom = (
66 self.motor_feedforward * (1 / self.J_bottom - 1 / self.J_top))
Austin Schuhc8ca2442013-02-23 12:29:33 -080067 self.B_continuous = numpy.matrix(
Austin Schuh0d9467a2014-02-15 22:36:45 -080068 [[0, 0],
James Kuszmaule2afbe42014-02-17 22:29:59 -080069 [0, 0],
James Kuszmaulc02a39a2014-02-18 15:45:16 -080070 [self.motor_feedforward_bottom, 0],
Austin Schuh170fe252014-02-22 15:52:01 -080071 [-self.motor_feedforward_bottom, self.motor_feedforward_difference]])
James Kuszmaule2afbe42014-02-17 22:29:59 -080072
James Kuszmaulc02a39a2014-02-18 15:45:16 -080073 print "Cont X_ss", self.motor_feedforward / -self.common_motor_constant
74
James Kuszmaule2afbe42014-02-17 22:29:59 -080075 self.B_bottom_cont = numpy.matrix(
76 [[0],
77 [self.motor_feedforward_bottom]])
78
79 self.B_diff_cont = numpy.matrix(
80 [[0],
81 [self.motor_feedforward_difference]])
82
Austin Schuh0d9467a2014-02-15 22:36:45 -080083 self.C = numpy.matrix([[1, 0, 0, 0],
James Kuszmaulc02a39a2014-02-18 15:45:16 -080084 [1, 1, 0, 0]])
Austin Schuh0d9467a2014-02-15 22:36:45 -080085 self.D = numpy.matrix([[0, 0],
86 [0, 0]])
Austin Schuhc8ca2442013-02-23 12:29:33 -080087
Austin Schuhc1f68892013-03-16 17:06:27 -070088 self.A, self.B = self.ContinuousToDiscrete(
89 self.A_continuous, self.B_continuous, self.dt)
Austin Schuhc8ca2442013-02-23 12:29:33 -080090
James Kuszmaule2afbe42014-02-17 22:29:59 -080091 self.A_bottom, self.B_bottom = controls.c2d(
92 self.A_bottom_cont, self.B_bottom_cont, self.dt)
93 self.A_diff, self.B_diff = controls.c2d(
94 self.A_diff_cont, self.B_diff_cont, self.dt)
95
Austin Schuh2758ade2014-02-22 16:58:21 -080096 self.K_bottom = controls.dplace(self.A_bottom, self.B_bottom, [.65, .45])
97 self.K_diff = controls.dplace(self.A_diff, self.B_diff, [.40, .28])
98
99 print "K_diff", self.K_diff
100 print "K_bottom", self.K_bottom
101
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800102 print "A"
103 print self.A
104 print "B"
105 print self.B
James Kuszmaule2afbe42014-02-17 22:29:59 -0800106
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800107
Austin Schuhcda86af2014-02-16 16:16:39 -0800108 self.Q = numpy.matrix([[(1.0 / (0.10 ** 2.0)), 0.0, 0.0, 0.0],
Austin Schuh01c652b2014-02-21 23:13:42 -0800109 [0.0, (1.0 / (0.06 ** 2.0)), 0.0, 0.0],
110 [0.0, 0.0, 0.10, 0.0],
111 [0.0, 0.0, 0.0, 0.1]])
Austin Schuhcda86af2014-02-16 16:16:39 -0800112
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800113 self.R = numpy.matrix([[(1.0 / (40.0 ** 2.0)), 0.0],
114 [0.0, (1.0 / (5.0 ** 2.0))]])
Austin Schuh170fe252014-02-22 15:52:01 -0800115 #self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
James Kuszmaule2afbe42014-02-17 22:29:59 -0800116
Austin Schuh2758ade2014-02-22 16:58:21 -0800117 self.K = numpy.matrix([[self.K_bottom[0, 0], 0.0, self.K_bottom[0, 1], 0.0],
118 [0.0, self.K_diff[0, 0], 0.0, self.K_diff[0, 1]]])
Austin Schuh170fe252014-02-22 15:52:01 -0800119
120 # Compute the feed forwards aceleration term.
121 self.K[1, 0] = -self.B[1, 0] * self.K[0, 0] / self.B[1, 1]
122
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800123 lstsq_A = numpy.identity(2)
Austin Schuh170fe252014-02-22 15:52:01 -0800124 lstsq_A[0, :] = self.B[1, :]
125 lstsq_A[1, :] = self.B[3, :]
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800126 print "System of Equations coefficients:"
Austin Schuh170fe252014-02-22 15:52:01 -0800127 print lstsq_A
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800128 print "det", numpy.linalg.det(lstsq_A)
Austin Schuh170fe252014-02-22 15:52:01 -0800129
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800130 out_x = numpy.linalg.lstsq(
131 lstsq_A,
132 numpy.matrix([[self.A[1, 2]], [self.A[3, 2]]]))[0]
133 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 -0800134
135 print "K unaugmented"
136 print self.K
James Kuszmaule2afbe42014-02-17 22:29:59 -0800137 print "B * K unaugmented"
138 print self.B * self.K
139 F = self.A - self.B * self.K
James Kuszmaule2afbe42014-02-17 22:29:59 -0800140 print "A - B * K unaugmented"
141 print F
142 print "eigenvalues"
143 print numpy.linalg.eig(F)[0]
Austin Schuhc8ca2442013-02-23 12:29:33 -0800144
145 self.rpl = .05
146 self.ipl = 0.008
Austin Schuh3c542312013-02-24 01:53:50 -0800147 self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
Austin Schuh0d9467a2014-02-15 22:36:45 -0800148 self.rpl + 1j * self.ipl,
James Kuszmaule2afbe42014-02-17 22:29:59 -0800149 self.rpl - 1j * self.ipl,
Austin Schuh3c542312013-02-24 01:53:50 -0800150 self.rpl - 1j * self.ipl])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800151
James Kuszmaul92797402014-02-17 14:08:49 -0800152 # The box formed by U_min and U_max must encompass all possible values,
153 # or else Austin's code gets angry.
James Kuszmauld536a402014-02-18 22:32:12 -0800154 self.U_max = numpy.matrix([[12.0], [12.0]])
155 self.U_min = numpy.matrix([[-12.0], [-12.0]])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800156
Austin Schuh2758ade2014-02-22 16:58:21 -0800157 # Compute the steady state velocities for a given applied voltage.
158 # The top and bottom of the claw should spin at the same rate if the
159 # physics is right.
160 X_ss = numpy.matrix([[0], [0], [0.0], [0]])
161
162 U = numpy.matrix([[1.0],[1.0]])
163 A = self.A
164 B = self.B
165 #X_ss[2, 0] = X_ss[2, 0] * A[2, 2] + B[2, 0] * U[0, 0]
166 X_ss[2, 0] = 1 / (1 - A[2, 2]) * B[2, 0] * U[0, 0]
167 #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]
168 #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]
169 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])
170 #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]
171 X_ss[0, 0] = A[0, 2] * X_ss[2, 0] + B[0, 0] * U[0, 0]
172 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]
173
174 print "X_ss", X_ss
175
Austin Schuhc1f68892013-03-16 17:06:27 -0700176 self.InitializeState()
177
178
Austin Schuh3bb9a442014-02-02 16:01:45 -0800179class ClawDeltaU(Claw):
180 def __init__(self, name="Claw"):
181 super(ClawDeltaU, self).__init__(name)
Austin Schuhc1f68892013-03-16 17:06:27 -0700182 A_unaugmented = self.A
183 B_unaugmented = self.B
Austin Schuh0d9467a2014-02-15 22:36:45 -0800184 C_unaugmented = self.C
Austin Schuhc1f68892013-03-16 17:06:27 -0700185
Austin Schuh0d9467a2014-02-15 22:36:45 -0800186 self.A = numpy.matrix([[0.0, 0.0, 0.0, 0.0, 0.0],
187 [0.0, 0.0, 0.0, 0.0, 0.0],
188 [0.0, 0.0, 0.0, 0.0, 0.0],
189 [0.0, 0.0, 0.0, 0.0, 0.0],
190 [0.0, 0.0, 0.0, 0.0, 1.0]])
191 self.A[0:4, 0:4] = A_unaugmented
192 self.A[0:4, 4] = B_unaugmented[0:4, 0]
Austin Schuhc1f68892013-03-16 17:06:27 -0700193
Austin Schuh0d9467a2014-02-15 22:36:45 -0800194 self.B = numpy.matrix([[0.0, 0.0],
195 [0.0, 0.0],
196 [0.0, 0.0],
197 [0.0, 0.0],
198 [1.0, 0.0]])
199 self.B[0:4, 1] = B_unaugmented[0:4, 1]
Austin Schuhc1f68892013-03-16 17:06:27 -0700200
Austin Schuh0d9467a2014-02-15 22:36:45 -0800201 self.C = numpy.concatenate((C_unaugmented, numpy.matrix([[0.0], [0.0]])),
202 axis=1)
203 self.D = numpy.matrix([[0.0, 0.0],
204 [0.0, 0.0]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700205
Austin Schuh0d9467a2014-02-15 22:36:45 -0800206 #self.PlaceControllerPoles([0.55, 0.35, 0.55, 0.35, 0.80])
207 self.Q = numpy.matrix([[(1.0 / (0.04 ** 2.0)), 0.0, 0.0, 0.0, 0.0],
208 [0.0, (1.0 / (0.01 ** 2)), 0.0, 0.0, 0.0],
209 [0.0, 0.0, 0.01, 0.0, 0.0],
210 [0.0, 0.0, 0.0, 0.08, 0.0],
211 [0.0, 0.0, 0.0, 0.0, (1.0 / (10.0 ** 2))]])
212
213 self.R = numpy.matrix([[0.000001, 0.0],
214 [0.0, 1.0 / (10.0 ** 2.0)]])
215 self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
216
217 self.K = numpy.matrix([[50.0, 0.0, 10.0, 0.0, 1.0],
218 [50.0, 0.0, 10.0, 0.0, 1.0]])
219 #self.K = numpy.matrix([[50.0, -100.0, 0, -10, 0],
220 # [50.0, 100.0, 0, 10, 0]])
221
222 controlability = controls.ctrb(self.A, self.B);
223 print "Rank of augmented controlability matrix.", numpy.linalg.matrix_rank(controlability)
Austin Schuhc1f68892013-03-16 17:06:27 -0700224
225 print "K"
226 print self.K
227 print "Placed controller poles are"
228 print numpy.linalg.eig(self.A - self.B * self.K)[0]
Austin Schuh0d9467a2014-02-15 22:36:45 -0800229 print [numpy.abs(x) for x in numpy.linalg.eig(self.A - self.B * self.K)[0]]
Austin Schuhc1f68892013-03-16 17:06:27 -0700230
231 self.rpl = .05
232 self.ipl = 0.008
Austin Schuh0d9467a2014-02-15 22:36:45 -0800233 self.PlaceObserverPoles([self.rpl + 1j * self.ipl, 0.10, 0.09,
Brian Silverman23a67ca2013-03-16 23:48:50 -0700234 self.rpl - 1j * self.ipl, 0.90])
Austin Schuh0d9467a2014-02-15 22:36:45 -0800235 #print "A is"
236 #print self.A
237 #print "L is"
238 #print self.L
239 #print "C is"
240 #print self.C
241 #print "A - LC is"
242 #print self.A - self.L * self.C
Austin Schuhc1f68892013-03-16 17:06:27 -0700243
Austin Schuh0d9467a2014-02-15 22:36:45 -0800244 #print "Placed observer poles are"
245 #print numpy.linalg.eig(self.A - self.L * self.C)[0]
246
247 self.U_max = numpy.matrix([[12.0], [12.0]])
248 self.U_min = numpy.matrix([[-12.0], [-12.0]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700249
250 self.InitializeState()
251
252
Austin Schuhcda86af2014-02-16 16:16:39 -0800253def FullSeparationPriority(claw, U):
254 bottom_u = U[0, 0]
Austin Schuh2758ade2014-02-22 16:58:21 -0800255 top_u = U[1, 0]
Austin Schuhcda86af2014-02-16 16:16:39 -0800256
Austin Schuhcda86af2014-02-16 16:16:39 -0800257 if bottom_u > claw.U_max[0, 0]:
Austin Schuhcda86af2014-02-16 16:16:39 -0800258 top_u -= bottom_u - claw.U_max[0, 0]
259 if top_u < claw.U_min[1, 0]:
260 top_u = claw.U_min[1, 0]
261
262 bottom_u = claw.U_max[0, 0]
263 if top_u > claw.U_max[1, 0]:
264 bottom_u -= top_u - claw.U_max[1, 0]
265 if bottom_u < claw.U_min[0, 0]:
266 bottom_u = claw.U_min[0, 0]
267
268 top_u = claw.U_max[1, 0]
269 if top_u < claw.U_min[1, 0]:
270 bottom_u -= top_u - claw.U_min[1, 0]
271 if bottom_u > claw.U_max[0, 0]:
272 bottom_u = claw.U_max[0, 0]
273
274 top_u = claw.U_min[1, 0]
275 if bottom_u < claw.U_min[0, 0]:
276 top_u -= bottom_u - claw.U_min[0, 0]
277 if top_u > claw.U_max[1, 0]:
278 top_u = claw.U_max[1, 0]
279
280 bottom_u = claw.U_min[0, 0]
281
Austin Schuh2758ade2014-02-22 16:58:21 -0800282 return numpy.matrix([[bottom_u], [top_u]])
Austin Schuhcda86af2014-02-16 16:16:39 -0800283
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800284def AverageUFix(claw, U, preserve_v3=False):
285 """Clips U as necessary.
Austin Schuhcda86af2014-02-16 16:16:39 -0800286
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800287 Args:
288 claw: claw object containing moments of inertia and U limits.
289 U: Input matrix to clip as necessary.
290 preserve_v3: There are two ways to attempt to clip the voltages:
Austin Schuh170fe252014-02-22 15:52:01 -0800291 -If you preserve the imaginary v3, then it will attempt to
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800292 preserve the effect on the separation of the two claws.
293 If it is not able to do this, then it calls itself with preserve_v3
294 set to False.
295 -If you preserve the ratio of the voltage of the bottom and the top,
296 then it will attempt to preserve the ratio of those two. This is
297 equivalent to preserving the ratio of v3 and the bottom voltage.
298 """
299 bottom_u = U[0, 0]
300 top_u = U[1, 0]
301 seperation_u = top_u - bottom_u * claw.J_top / claw.J_bottom
302
Austin Schuh2758ade2014-02-22 16:58:21 -0800303 bottom_bad = bottom_u > claw.U_max[0, 0] or bottom_u < claw.U_min[0, 0]
Austin Schuh170fe252014-02-22 15:52:01 -0800304 top_bad = top_u > claw.U_max[0, 0] or top_u < claw.U_min[0, 0]
305
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800306 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
Austin Schuh2758ade2014-02-22 16:58:21 -0800320 print "Scaling"
Austin Schuhcda86af2014-02-16 16:16:39 -0800321
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800322 return numpy.matrix([[bottom_u], [top_u]])
Austin Schuhcda86af2014-02-16 16:16:39 -0800323
Austin Schuh0d9467a2014-02-15 22:36:45 -0800324def ClipDeltaU(claw, U):
325 delta_u = U[0, 0]
326 top_u = U[1, 0]
327 old_bottom_u = claw.X[4, 0]
328
329 # TODO(austin): Preserve the difference between the top and bottom power.
330 new_unclipped_bottom_u = old_bottom_u + delta_u
331
332 #print "Bottom is", new_unclipped_bottom_u, "Top is", top_u
333 if new_unclipped_bottom_u > claw.U_max[0, 0]:
Austin Schuh0d9467a2014-02-15 22:36:45 -0800334 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]])
Austin Schuh2758ade2014-02-22 16:58:21 -0800373 claw.X[0, 0] = 1.0
374 claw.X[1, 0] = 0.0
375 claw.X[2, 0] = 0.0
376 claw.X[3, 0] = 0.0
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800377 claw.X_hat = claw.X
Austin Schuh2758ade2014-02-22 16:58:21 -0800378 #X_actual = claw.X
Austin Schuhcda86af2014-02-16 16:16:39 -0800379 for i in xrange(100):
380 #print "Error is", (R - claw.X_hat)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800381 U = claw.K * (R - claw.X)
Austin Schuhcda86af2014-02-16 16:16:39 -0800382 #U = numpy.clip(claw.K * (R - claw.X_hat), claw.U_min, claw.U_max)
383 #U = FullSeparationPriority(claw, U)
Austin Schuh2758ade2014-02-22 16:58:21 -0800384 U = AverageUFix(claw, U, preserve_v3=False)
Austin Schuhcda86af2014-02-16 16:16:39 -0800385 #U = claw.K * (R - claw.X_hat)
386 #U = ClipDeltaU(claw, U)
387 claw.UpdateObserver(U)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800388 claw.Update(U)
Austin Schuh2758ade2014-02-22 16:58:21 -0800389 #X_actual = claw.A_actual * X_actual + claw.B_actual * U
390 #claw.Y = claw.C * X_actual
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800391 close_loop_x_bottom.append(claw.X[0, 0] * 10)
Austin Schuhcda86af2014-02-16 16:16:39 -0800392 close_loop_u_bottom.append(U[0, 0])
Austin Schuh2758ade2014-02-22 16:58:21 -0800393 #actual_sep.append(X_actual[2, 0] * 100)
394 #actual_x_bottom.append(X_actual[0, 0] * 10)
395 close_loop_x_sep.append(claw.X[1, 0] * 10)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800396 close_loop_x_top.append((claw.X[1, 0] + claw.X[0, 0]) * 10)
397 close_loop_u_top.append(U[1, 0])
Austin Schuhcda86af2014-02-16 16:16:39 -0800398 t.append(0.01 * i)
Austin Schuhc8ca2442013-02-23 12:29:33 -0800399
Austin Schuh2758ade2014-02-22 16:58:21 -0800400 pylab.plot(t, close_loop_x_bottom, label='x bottom * 10')
401 pylab.plot(t, close_loop_x_sep, label='separation * 10')
402 #pylab.plot(t, actual_x_bottom, label='true x bottom')
403 #pylab.plot(t, actual_sep, label='true separation')
404 pylab.plot(t, close_loop_x_top, label='x top * 10')
Austin Schuhcda86af2014-02-16 16:16:39 -0800405 pylab.plot(t, close_loop_u_bottom, label='u bottom')
406 pylab.plot(t, close_loop_u_top, label='u top')
Austin Schuh0d9467a2014-02-15 22:36:45 -0800407 pylab.legend()
Austin Schuhfa033692013-02-24 01:00:55 -0800408 pylab.show()
Austin Schuhc8ca2442013-02-23 12:29:33 -0800409
Austin Schuh3c542312013-02-24 01:53:50 -0800410 # Write the generated constants out to a file.
Austin Schuhcda86af2014-02-16 16:16:39 -0800411 if len(argv) != 3:
412 print "Expected .h file name and .cc file name for the claw."
Austin Schuhc8ca2442013-02-23 12:29:33 -0800413 else:
Austin Schuhcda86af2014-02-16 16:16:39 -0800414 claw = Claw("Claw")
415 loop_writer = control_loop.ControlLoopWriter("Claw", [claw])
Austin Schuh683a0d02013-03-02 01:51:31 -0800416 if argv[1][-3:] == '.cc':
Austin Schuhcda86af2014-02-16 16:16:39 -0800417 loop_writer.Write(argv[2], argv[1])
Austin Schuh683a0d02013-03-02 01:51:31 -0800418 else:
Austin Schuhcda86af2014-02-16 16:16:39 -0800419 loop_writer.Write(argv[1], argv[2])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800420
421if __name__ == '__main__':
422 sys.exit(main(sys.argv))