blob: f07ab2c83d8a74824e65c1fdf2af620d92cdf414 [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
James Kuszmaulc02a39a2014-02-18 15:45:16 -080096 print "A"
97 print self.A
98 print "B"
99 print self.B
James Kuszmaule2afbe42014-02-17 22:29:59 -0800100
Austin Schuh170fe252014-02-22 15:52:01 -0800101 # Compute the steady state velocities for a given applied voltage.
102 # The top and bottom of the claw should spin at the same rate if the
103 # physics is right.
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800104 X_ss = numpy.matrix([[0], [0], [0.0], [0]])
105
106 U = numpy.matrix([[1.0],[1.0]])
107 A = self.A
108 B = self.B
Austin Schuh170fe252014-02-22 15:52:01 -0800109 #X_ss[2, 0] = X_ss[2, 0] * A[2, 2] + B[2, 0] * U[0, 0]
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800110 X_ss[2, 0] = 1 / (1 - A[2, 2]) * B[2, 0] * U[0, 0]
Austin Schuh170fe252014-02-22 15:52:01 -0800111 #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]
112 #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]
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800113 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])
Austin Schuh170fe252014-02-22 15:52:01 -0800114 #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]
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800115 X_ss[0, 0] = A[0, 2] * X_ss[2, 0] + B[0, 0] * U[0, 0]
116 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]
117
118 print "X_ss", X_ss
119
Austin Schuhcda86af2014-02-16 16:16:39 -0800120 self.Q = numpy.matrix([[(1.0 / (0.10 ** 2.0)), 0.0, 0.0, 0.0],
Austin Schuh01c652b2014-02-21 23:13:42 -0800121 [0.0, (1.0 / (0.06 ** 2.0)), 0.0, 0.0],
122 [0.0, 0.0, 0.10, 0.0],
123 [0.0, 0.0, 0.0, 0.1]])
Austin Schuhcda86af2014-02-16 16:16:39 -0800124
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800125 self.R = numpy.matrix([[(1.0 / (40.0 ** 2.0)), 0.0],
126 [0.0, (1.0 / (5.0 ** 2.0))]])
Austin Schuh170fe252014-02-22 15:52:01 -0800127 #self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
James Kuszmaule2afbe42014-02-17 22:29:59 -0800128
Austin Schuh170fe252014-02-22 15:52:01 -0800129 self.K = numpy.matrix([[50, 0.0, 1.0, 0.0],
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800130 [0.0, 300, 0.0, 1.1]])
Austin Schuh170fe252014-02-22 15:52:01 -0800131
132 # Compute the feed forwards aceleration term.
133 self.K[1, 0] = -self.B[1, 0] * self.K[0, 0] / self.B[1, 1]
134
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800135 lstsq_A = numpy.identity(2)
Austin Schuh170fe252014-02-22 15:52:01 -0800136 lstsq_A[0, :] = self.B[1, :]
137 lstsq_A[1, :] = self.B[3, :]
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800138 print "System of Equations coefficients:"
Austin Schuh170fe252014-02-22 15:52:01 -0800139 print lstsq_A
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800140 print "det", numpy.linalg.det(lstsq_A)
Austin Schuh170fe252014-02-22 15:52:01 -0800141
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800142 out_x = numpy.linalg.lstsq(
143 lstsq_A,
144 numpy.matrix([[self.A[1, 2]], [self.A[3, 2]]]))[0]
145 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 -0800146
147 print "K unaugmented"
148 print self.K
James Kuszmaule2afbe42014-02-17 22:29:59 -0800149 print "B * K unaugmented"
150 print self.B * self.K
151 F = self.A - self.B * self.K
James Kuszmaule2afbe42014-02-17 22:29:59 -0800152 print "A - B * K unaugmented"
153 print F
154 print "eigenvalues"
155 print numpy.linalg.eig(F)[0]
Austin Schuhc8ca2442013-02-23 12:29:33 -0800156
157 self.rpl = .05
158 self.ipl = 0.008
Austin Schuh3c542312013-02-24 01:53:50 -0800159 self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
Austin Schuh0d9467a2014-02-15 22:36:45 -0800160 self.rpl + 1j * self.ipl,
James Kuszmaule2afbe42014-02-17 22:29:59 -0800161 self.rpl - 1j * self.ipl,
Austin Schuh3c542312013-02-24 01:53:50 -0800162 self.rpl - 1j * self.ipl])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800163
James Kuszmaul92797402014-02-17 14:08:49 -0800164 # The box formed by U_min and U_max must encompass all possible values,
165 # or else Austin's code gets angry.
James Kuszmauld536a402014-02-18 22:32:12 -0800166 self.U_max = numpy.matrix([[12.0], [12.0]])
167 self.U_min = numpy.matrix([[-12.0], [-12.0]])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800168
Austin Schuhc1f68892013-03-16 17:06:27 -0700169 self.InitializeState()
170
171
Austin Schuh3bb9a442014-02-02 16:01:45 -0800172class ClawDeltaU(Claw):
173 def __init__(self, name="Claw"):
174 super(ClawDeltaU, self).__init__(name)
Austin Schuhc1f68892013-03-16 17:06:27 -0700175 A_unaugmented = self.A
176 B_unaugmented = self.B
Austin Schuh0d9467a2014-02-15 22:36:45 -0800177 C_unaugmented = self.C
Austin Schuhc1f68892013-03-16 17:06:27 -0700178
Austin Schuh0d9467a2014-02-15 22:36:45 -0800179 self.A = numpy.matrix([[0.0, 0.0, 0.0, 0.0, 0.0],
180 [0.0, 0.0, 0.0, 0.0, 0.0],
181 [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, 1.0]])
184 self.A[0:4, 0:4] = A_unaugmented
185 self.A[0:4, 4] = B_unaugmented[0:4, 0]
Austin Schuhc1f68892013-03-16 17:06:27 -0700186
Austin Schuh0d9467a2014-02-15 22:36:45 -0800187 self.B = numpy.matrix([[0.0, 0.0],
188 [0.0, 0.0],
189 [0.0, 0.0],
190 [0.0, 0.0],
191 [1.0, 0.0]])
192 self.B[0:4, 1] = B_unaugmented[0:4, 1]
Austin Schuhc1f68892013-03-16 17:06:27 -0700193
Austin Schuh0d9467a2014-02-15 22:36:45 -0800194 self.C = numpy.concatenate((C_unaugmented, numpy.matrix([[0.0], [0.0]])),
195 axis=1)
196 self.D = numpy.matrix([[0.0, 0.0],
197 [0.0, 0.0]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700198
Austin Schuh0d9467a2014-02-15 22:36:45 -0800199 #self.PlaceControllerPoles([0.55, 0.35, 0.55, 0.35, 0.80])
200 self.Q = numpy.matrix([[(1.0 / (0.04 ** 2.0)), 0.0, 0.0, 0.0, 0.0],
201 [0.0, (1.0 / (0.01 ** 2)), 0.0, 0.0, 0.0],
202 [0.0, 0.0, 0.01, 0.0, 0.0],
203 [0.0, 0.0, 0.0, 0.08, 0.0],
204 [0.0, 0.0, 0.0, 0.0, (1.0 / (10.0 ** 2))]])
205
206 self.R = numpy.matrix([[0.000001, 0.0],
207 [0.0, 1.0 / (10.0 ** 2.0)]])
208 self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
209
210 self.K = numpy.matrix([[50.0, 0.0, 10.0, 0.0, 1.0],
211 [50.0, 0.0, 10.0, 0.0, 1.0]])
212 #self.K = numpy.matrix([[50.0, -100.0, 0, -10, 0],
213 # [50.0, 100.0, 0, 10, 0]])
214
215 controlability = controls.ctrb(self.A, self.B);
216 print "Rank of augmented controlability matrix.", numpy.linalg.matrix_rank(controlability)
Austin Schuhc1f68892013-03-16 17:06:27 -0700217
218 print "K"
219 print self.K
220 print "Placed controller poles are"
221 print numpy.linalg.eig(self.A - self.B * self.K)[0]
Austin Schuh0d9467a2014-02-15 22:36:45 -0800222 print [numpy.abs(x) for x in numpy.linalg.eig(self.A - self.B * self.K)[0]]
Austin Schuhc1f68892013-03-16 17:06:27 -0700223
224 self.rpl = .05
225 self.ipl = 0.008
Austin Schuh0d9467a2014-02-15 22:36:45 -0800226 self.PlaceObserverPoles([self.rpl + 1j * self.ipl, 0.10, 0.09,
Brian Silverman23a67ca2013-03-16 23:48:50 -0700227 self.rpl - 1j * self.ipl, 0.90])
Austin Schuh0d9467a2014-02-15 22:36:45 -0800228 #print "A is"
229 #print self.A
230 #print "L is"
231 #print self.L
232 #print "C is"
233 #print self.C
234 #print "A - LC is"
235 #print self.A - self.L * self.C
Austin Schuhc1f68892013-03-16 17:06:27 -0700236
Austin Schuh0d9467a2014-02-15 22:36:45 -0800237 #print "Placed observer poles are"
238 #print numpy.linalg.eig(self.A - self.L * self.C)[0]
239
240 self.U_max = numpy.matrix([[12.0], [12.0]])
241 self.U_min = numpy.matrix([[-12.0], [-12.0]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700242
243 self.InitializeState()
244
245
Austin Schuhcda86af2014-02-16 16:16:39 -0800246def FullSeparationPriority(claw, U):
247 bottom_u = U[0, 0]
248 top_u = U[1, 0] + bottom_u
249
250 #print "Bottom is", new_unclipped_bottom_u, "Top is", top_u
251 if bottom_u > claw.U_max[0, 0]:
252 #print "Bottom is too big. Was", new_unclipped_bottom_u, "changing top by", new_unclipped_bottom_u - claw.U_max[0, 0]
253 top_u -= bottom_u - claw.U_max[0, 0]
254 if top_u < claw.U_min[1, 0]:
255 top_u = claw.U_min[1, 0]
256
257 bottom_u = claw.U_max[0, 0]
258 if top_u > claw.U_max[1, 0]:
259 bottom_u -= top_u - claw.U_max[1, 0]
260 if bottom_u < claw.U_min[0, 0]:
261 bottom_u = claw.U_min[0, 0]
262
263 top_u = claw.U_max[1, 0]
264 if top_u < claw.U_min[1, 0]:
265 bottom_u -= top_u - claw.U_min[1, 0]
266 if bottom_u > claw.U_max[0, 0]:
267 bottom_u = claw.U_max[0, 0]
268
269 top_u = claw.U_min[1, 0]
270 if bottom_u < claw.U_min[0, 0]:
271 top_u -= bottom_u - claw.U_min[0, 0]
272 if top_u > claw.U_max[1, 0]:
273 top_u = claw.U_max[1, 0]
274
275 bottom_u = claw.U_min[0, 0]
276
277 return numpy.matrix([[bottom_u], [top_u - bottom_u]])
278
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800279def AverageUFix(claw, U, preserve_v3=False):
280 """Clips U as necessary.
Austin Schuhcda86af2014-02-16 16:16:39 -0800281
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800282 Args:
283 claw: claw object containing moments of inertia and U limits.
284 U: Input matrix to clip as necessary.
285 preserve_v3: There are two ways to attempt to clip the voltages:
Austin Schuh170fe252014-02-22 15:52:01 -0800286 -If you preserve the imaginary v3, then it will attempt to
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800287 preserve the effect on the separation of the two claws.
288 If it is not able to do this, then it calls itself with preserve_v3
289 set to False.
290 -If you preserve the ratio of the voltage of the bottom and the top,
291 then it will attempt to preserve the ratio of those two. This is
292 equivalent to preserving the ratio of v3 and the bottom voltage.
293 """
294 bottom_u = U[0, 0]
295 top_u = U[1, 0]
296 seperation_u = top_u - bottom_u * claw.J_top / claw.J_bottom
297
Austin Schuh170fe252014-02-22 15:52:01 -0800298 bottom_bad = bottom_u > claw.U_max[0, 0] or top_u < claw.U_min[0, 0]
299 top_bad = top_u > claw.U_max[0, 0] or top_u < claw.U_min[0, 0]
300
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800301 scalar = claw.U_max[0, 0] / max(numpy.abs(top_u), numpy.abs(bottom_u))
302 if bottom_bad and preserve_v3:
303 bottom_u *= scalar
304 top_u = seperation_u + bottom_u * claw.J_top / claw.J_bottom
305 if abs(top_u) > claw.U_max[0, 0]:
306 return AverageUFix(claw, U, preserve_v3=False)
307 elif top_bad and preserve_v3:
308 top_u *= scalar
309 bottom_u = (top_u - seperation_u) * claw.J_bottom / claw.J_top
310 if abs(bottom_u) > claw.U_max[0, 0]:
311 return AverageUFix(claw, U, preserve_v3=False)
312 elif (bottom_bad or top_bad) and not preserve_v3:
Austin Schuhcda86af2014-02-16 16:16:39 -0800313 top_u *= scalar
314 bottom_u *= scalar
315
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800316 return numpy.matrix([[bottom_u], [top_u]])
Austin Schuhcda86af2014-02-16 16:16:39 -0800317
Austin Schuh0d9467a2014-02-15 22:36:45 -0800318def ClipDeltaU(claw, U):
319 delta_u = U[0, 0]
320 top_u = U[1, 0]
321 old_bottom_u = claw.X[4, 0]
322
323 # TODO(austin): Preserve the difference between the top and bottom power.
324 new_unclipped_bottom_u = old_bottom_u + delta_u
325
326 #print "Bottom is", new_unclipped_bottom_u, "Top is", top_u
327 if new_unclipped_bottom_u > claw.U_max[0, 0]:
Austin Schuh0d9467a2014-02-15 22:36:45 -0800328 top_u -= new_unclipped_bottom_u - claw.U_max[0, 0]
329 new_unclipped_bottom_u = claw.U_max[0, 0]
330 if top_u > claw.U_max[1, 0]:
331 new_unclipped_bottom_u -= top_u - claw.U_max[1, 0]
332 top_u = claw.U_max[1, 0]
333 if top_u < claw.U_min[1, 0]:
334 new_unclipped_bottom_u -= top_u - claw.U_min[1, 0]
335 top_u = claw.U_min[1, 0]
336 if new_unclipped_bottom_u < claw.U_min[0, 0]:
337 top_u -= new_unclipped_bottom_u - claw.U_min[0, 0]
338 new_unclipped_bottom_u = claw.U_min[0, 0]
339
340 new_bottom_u = numpy.clip(new_unclipped_bottom_u, claw.U_min[0, 0], claw.U_max[0, 0])
341 new_top_u = numpy.clip(top_u, claw.U_min[1, 0], claw.U_max[1, 0])
342
343 return numpy.matrix([[new_bottom_u - old_bottom_u], [new_top_u]])
Austin Schuhc1f68892013-03-16 17:06:27 -0700344
Austin Schuhc8ca2442013-02-23 12:29:33 -0800345def main(argv):
Austin Schuh3c542312013-02-24 01:53:50 -0800346 # Simulate the response of the system to a step input.
Austin Schuh0d9467a2014-02-15 22:36:45 -0800347 #claw = ClawDeltaU()
348 #simulated_x = []
349 #for _ in xrange(100):
350 # claw.Update(numpy.matrix([[12.0]]))
351 # simulated_x.append(claw.X[0, 0])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800352
Austin Schuh0d9467a2014-02-15 22:36:45 -0800353 #pylab.plot(range(100), simulated_x)
354 #pylab.show()
Austin Schuhc8ca2442013-02-23 12:29:33 -0800355
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800356 # Simulate the closed loop response of the system.
Austin Schuhcda86af2014-02-16 16:16:39 -0800357 claw = Claw("TopClaw")
358 t = []
Austin Schuh0d9467a2014-02-15 22:36:45 -0800359 close_loop_x_bottom = []
360 close_loop_x_sep = []
James Kuszmaul4e4ec8e2014-02-18 10:46:49 -0800361 actual_sep = []
362 actual_x_bottom = []
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800363 close_loop_x_top = []
Austin Schuh0d9467a2014-02-15 22:36:45 -0800364 close_loop_u_bottom = []
365 close_loop_u_top = []
James Kuszmaul4e4ec8e2014-02-18 10:46:49 -0800366 R = numpy.matrix([[0.0], [0.00], [0.0], [0.0]])
367 claw.X[0, 0] = 1
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800368 claw.X[1, 0] = .0
369 claw.X_hat = claw.X
370 #X_actual = claw.X
Austin Schuhcda86af2014-02-16 16:16:39 -0800371 for i in xrange(100):
372 #print "Error is", (R - claw.X_hat)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800373 U = claw.K * (R - claw.X)
Austin Schuhcda86af2014-02-16 16:16:39 -0800374 #U = numpy.clip(claw.K * (R - claw.X_hat), claw.U_min, claw.U_max)
375 #U = FullSeparationPriority(claw, U)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800376 #U = AverageUFix(claw, U, preserve_v3=True)
Austin Schuhcda86af2014-02-16 16:16:39 -0800377 #U = claw.K * (R - claw.X_hat)
378 #U = ClipDeltaU(claw, U)
379 claw.UpdateObserver(U)
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800380 claw.Update(U)
381 #X_actual = claw.A_actual * X_actual + claw.B_actual * U
382 #claw.Y = claw.C * X_actual
383 close_loop_x_bottom.append(claw.X[0, 0] * 10)
Austin Schuhcda86af2014-02-16 16:16:39 -0800384 close_loop_u_bottom.append(U[0, 0])
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800385 #actual_sep.append(X_actual[2, 0] * 100)
386 #actual_x_bottom.append(X_actual[0, 0] * 10)
387 close_loop_x_sep.append(claw.X[1, 0] * 100)
388 close_loop_x_top.append((claw.X[1, 0] + claw.X[0, 0]) * 10)
389 close_loop_u_top.append(U[1, 0])
Austin Schuhcda86af2014-02-16 16:16:39 -0800390 t.append(0.01 * i)
Austin Schuhc8ca2442013-02-23 12:29:33 -0800391
Austin Schuhcda86af2014-02-16 16:16:39 -0800392 pylab.plot(t, close_loop_x_bottom, label='x bottom')
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800393 pylab.plot(t, close_loop_x_sep, label='separation')
James Kuszmaulc02a39a2014-02-18 15:45:16 -0800394 #pylab.plot(t, actual_x_bottom, label='true x bottom')
395 #pylab.plot(t, actual_sep, label='true separation')
James Kuszmaulf2ed6e62014-02-17 17:52:07 -0800396 pylab.plot(t, close_loop_x_top, label='x top')
Austin Schuhcda86af2014-02-16 16:16:39 -0800397 pylab.plot(t, close_loop_u_bottom, label='u bottom')
398 pylab.plot(t, close_loop_u_top, label='u top')
Austin Schuh0d9467a2014-02-15 22:36:45 -0800399 pylab.legend()
Austin Schuhfa033692013-02-24 01:00:55 -0800400 pylab.show()
Austin Schuhc8ca2442013-02-23 12:29:33 -0800401
Austin Schuh3c542312013-02-24 01:53:50 -0800402 # Write the generated constants out to a file.
Austin Schuhcda86af2014-02-16 16:16:39 -0800403 if len(argv) != 3:
404 print "Expected .h file name and .cc file name for the claw."
Austin Schuhc8ca2442013-02-23 12:29:33 -0800405 else:
Austin Schuhcda86af2014-02-16 16:16:39 -0800406 claw = Claw("Claw")
407 loop_writer = control_loop.ControlLoopWriter("Claw", [claw])
Austin Schuh683a0d02013-03-02 01:51:31 -0800408 if argv[1][-3:] == '.cc':
Austin Schuhcda86af2014-02-16 16:16:39 -0800409 loop_writer.Write(argv[2], argv[1])
Austin Schuh683a0d02013-03-02 01:51:31 -0800410 else:
Austin Schuhcda86af2014-02-16 16:16:39 -0800411 loop_writer.Write(argv[1], argv[2])
Austin Schuhc8ca2442013-02-23 12:29:33 -0800412
413if __name__ == '__main__':
414 sys.exit(main(sys.argv))