blob: 3c87e861e218b3fc57a4a832c92e4dab52556cc3 [file] [log] [blame]
James Kuszmaul4a4622b2013-03-02 16:28:29 -08001#!/usr/bin/python
2
3import control_loop
4import numpy
5import sys
6from matplotlib import pylab
7
8class AngleAdjust(control_loop.ControlLoop):
Austin Schuhc1f68892013-03-16 17:06:27 -07009 def __init__(self, name="AngleAdjustRaw"):
10 super(AngleAdjust, self).__init__(name)
James Kuszmaul4a4622b2013-03-02 16:28:29 -080011 # Stall Torque in N m
12 self.stall_torque = .428
13 # Stall Current in Amps
14 self.stall_current = 63.8
15 # Free Speed in RPM
Austin Schuh72e26772013-03-10 18:15:39 -070016 self.free_speed = 14900.0
James Kuszmaul4a4622b2013-03-02 16:28:29 -080017 # Free Current in Amps
18 self.free_current = 1.2
19 # Moment of inertia of the angle adjust about the shooter's pivot in kg m^2
Austin Schuh72e26772013-03-10 18:15:39 -070020 self.J = 9.4
James Kuszmaul4a4622b2013-03-02 16:28:29 -080021 # Resistance of the motor
22 self.R = 12.0 / self.stall_current
23 # Motor velocity constant
24 self.Kv = ((self.free_speed / 60.0 * 2.0 * numpy.pi) /
25 (12.0 - self.R * self.free_current))
26 # Torque constant
27 self.Kt = self.stall_torque / self.stall_current
28 # Gear ratio of the gearbox multiplied by the ratio of the radii of
29 # the output and the angle adjust curve, which is essentially another gear.
30 self.G = (1.0 / 50.0) * (0.01905 / 0.41964)
31 # Control loop time step
32 self.dt = 0.01
33
34 # State feedback matrices
35 self.A_continuous = numpy.matrix(
36 [[0, 1],
37 [0, -self.Kt / self.Kv / (self.J * self.G * self.G * self.R)]])
38 self.B_continuous = numpy.matrix(
39 [[0],
40 [self.Kt / (self.J * self.G * self.R)]])
41 self.C = numpy.matrix([[1, 0]])
42 self.D = numpy.matrix([[0]])
43
Austin Schuhc1f68892013-03-16 17:06:27 -070044 self.A, self.B = self.ContinuousToDiscrete(
45 self.A_continuous, self.B_continuous, self.dt)
James Kuszmaul4a4622b2013-03-02 16:28:29 -080046
Austin Schuhe3490622013-03-13 01:24:30 -070047 self.PlaceControllerPoles([.45, .8])
James Kuszmaul4a4622b2013-03-02 16:28:29 -080048
Austin Schuhc1f68892013-03-16 17:06:27 -070049 print "Unaugmented controller poles at"
50 print self.K
51
James Kuszmaul4a4622b2013-03-02 16:28:29 -080052 self.rpl = .05
53 self.ipl = 0.008
54 self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
55 self.rpl - 1j * self.ipl])
56
57 self.U_max = numpy.matrix([[12.0]])
58 self.U_min = numpy.matrix([[-12.0]])
59
Austin Schuhc1f68892013-03-16 17:06:27 -070060 self.InitializeState()
61
62class AngleAdjustDeltaU(AngleAdjust):
63 def __init__(self, name="AngleAdjust"):
64 super(AngleAdjustDeltaU, self).__init__(name)
65 A_unaugmented = self.A
66 B_unaugmented = self.B
67
68 self.A = numpy.matrix([[0.0, 0.0, 0.0],
69 [0.0, 0.0, 0.0],
70 [0.0, 0.0, 1.0]])
71 self.A[0:2, 0:2] = A_unaugmented
72 self.A[0:2, 2] = B_unaugmented
73
74 self.B = numpy.matrix([[0.0],
75 [0.0],
76 [1.0]])
77
78 self.C = numpy.matrix([[1.0, 0.0, 0.0]])
79 self.D = numpy.matrix([[0.0]])
80
81 self.PlaceControllerPoles([0.60, 0.35, 0.80])
82
83 print "K"
84 print self.K
85 print "Placed controller poles are"
86 print numpy.linalg.eig(self.A - self.B * self.K)[0]
87
88 self.rpl = .05
89 self.ipl = 0.008
90 self.PlaceObserverPoles([self.rpl + 1j * self.ipl,
91 self.rpl - 1j * self.ipl, 0.15])
92 print "Placed observer poles are"
93 print numpy.linalg.eig(self.A - self.L * self.C)[0]
94
95 self.U_max = numpy.matrix([[12.0]])
96 self.U_min = numpy.matrix([[-12.0]])
97
98 self.InitializeState()
99
100
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800101def main(argv):
102 # Simulate the response of the system to a step input.
Austin Schuh72e26772013-03-10 18:15:39 -0700103 angle_adjust_data = numpy.genfromtxt(
104 'angle_adjust/angle_adjust_data.csv', delimiter=',')
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800105 angle_adjust = AngleAdjust()
106 simulated_x = []
Austin Schuh72e26772013-03-10 18:15:39 -0700107 real_x = []
108 initial_x = angle_adjust_data[0, 2]
109 for i in xrange(angle_adjust_data.shape[0]):
110 angle_adjust.Update(numpy.matrix([[angle_adjust_data[i, 1] - 0.7]]))
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800111 simulated_x.append(angle_adjust.X[0, 0])
Austin Schuh72e26772013-03-10 18:15:39 -0700112 x_offset = angle_adjust_data[i, 2] - initial_x
113 real_x.append(x_offset)
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800114
Austin Schuh72e26772013-03-10 18:15:39 -0700115 sim_delay = 2
116 pylab.plot(range(sim_delay, angle_adjust_data.shape[0] + sim_delay),
117 simulated_x, label='Simulation')
118 pylab.plot(range(angle_adjust_data.shape[0]), real_x, label='Reality')
119 pylab.legend()
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800120 pylab.show()
121
122 # Simulate the closed loop response of the system to a step input.
Austin Schuhc1f68892013-03-16 17:06:27 -0700123 angle_adjust = AngleAdjustDeltaU()
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800124 close_loop_x = []
Austin Schuhc1f68892013-03-16 17:06:27 -0700125 R = numpy.matrix([[1.0], [0.0], [0.0]])
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800126 for _ in xrange(100):
127 U = numpy.clip(angle_adjust.K * (R - angle_adjust.X_hat), angle_adjust.U_min, angle_adjust.U_max)
128 angle_adjust.UpdateObserver(U)
129 angle_adjust.Update(U)
130 close_loop_x.append(angle_adjust.X[0, 0])
131
132 pylab.plot(range(100), close_loop_x)
133 pylab.show()
134
135 # Write the generated constants out to a file.
Austin Schuhc1f68892013-03-16 17:06:27 -0700136 if len(argv) != 5:
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800137 print "Expected .cc file name and .h file name"
138 else:
Austin Schuhc1f68892013-03-16 17:06:27 -0700139 loop_writer = control_loop.ControlLoopWriter("RawAngleAdjust",
140 [AngleAdjust()])
141 if argv[3][-3:] == '.cc':
142 loop_writer.Write(argv[4], argv[3])
143 else:
144 loop_writer.Write(argv[3], argv[4])
145
Austin Schuhe3490622013-03-13 01:24:30 -0700146 loop_writer = control_loop.ControlLoopWriter("AngleAdjust", [angle_adjust])
Austin Schuh72e26772013-03-10 18:15:39 -0700147 if argv[1][-3:] == '.cc':
Austin Schuhe3490622013-03-13 01:24:30 -0700148 loop_writer.Write(argv[2], argv[1])
Austin Schuh72e26772013-03-10 18:15:39 -0700149 else:
Austin Schuhe3490622013-03-13 01:24:30 -0700150 loop_writer.Write(argv[1], argv[2])
James Kuszmaul4a4622b2013-03-02 16:28:29 -0800151
152if __name__ == '__main__':
153 sys.exit(main(sys.argv))