blob: 3c479341e7b59455c087b91ebbd76ec2e2e80cfa [file] [log] [blame]
Austin Schuh085eab92020-11-26 13:54:51 -08001#!/usr/bin/python3
Austin Schuha88c4072016-02-06 14:31:03 -08002
3import numpy
4import sys
5import operator
6
7from frc971.control_loops.python import control_loop
8from frc971.control_loops.python import controls
9
10from y2016.control_loops.python.shoulder import Shoulder, IntegralShoulder
11from y2016.control_loops.python.wrist import Wrist, IntegralWrist
John Park33858a32018-09-28 23:05:48 -070012from aos.util.trapezoid_profile import TrapezoidProfile
Austin Schuha88c4072016-02-06 14:31:03 -080013
14from matplotlib import pylab
15import gflags
16import glog
17
18FLAGS = gflags.FLAGS
19
20try:
Tyler Chatow6738c362019-02-16 14:12:30 -080021 gflags.DEFINE_bool('plot', False, 'If true, plot the loop response.')
Austin Schuha88c4072016-02-06 14:31:03 -080022except gflags.DuplicateFlagError:
Tyler Chatow6738c362019-02-16 14:12:30 -080023 pass
Austin Schuha88c4072016-02-06 14:31:03 -080024
25
26class Arm(control_loop.ControlLoop):
Austin Schuha88c4072016-02-06 14:31:03 -080027
Tyler Chatow6738c362019-02-16 14:12:30 -080028 def __init__(self, name="Arm", J=None):
29 super(Arm, self).__init__(name=name)
30 self._shoulder = Shoulder(name=name, J=J)
31 self._shooter = Wrist(name=name)
32 self.shoulder_Kv = self._shoulder.Kv / self._shoulder.G
Austin Schuha88c4072016-02-06 14:31:03 -080033
Tyler Chatow6738c362019-02-16 14:12:30 -080034 # Do a coordinate transformation.
35 # X_shooter_grounded = X_shooter + X_shoulder
36 # dX_shooter_grounded/dt = A_shooter * X_shooter + A_shoulder * X_shoulder +
37 # B_shoulder * U_shoulder + B_shooter * U_shooter
38 # dX_shooter_grounded/dt = A_shooter * (X_shooter_grounded - X_shoulder) +
39 # A_shoulder * X_shoulder + B_shooter * U_shooter + B_shoulder * U_shoulder
40 # X = [X_shoulder; X_shooter + X_shoulder]
41 # dX/dt = [A_shoulder 0] [X_shoulder ] + [B_shoulder 0] [U_shoulder]
42 # [(A_shoulder - A_shooter) A_shooter] [X_shooter_grounded] + [B_shoulder B_shooter] [ U_shooter]
43 # Y_shooter_grounded = Y_shooter + Y_shoulder
Austin Schuha88c4072016-02-06 14:31:03 -080044
Tyler Chatow6738c362019-02-16 14:12:30 -080045 self.A_continuous = numpy.matrix(numpy.zeros((4, 4)))
46 self.A_continuous[0:2, 0:2] = self._shoulder.A_continuous
47 self.A_continuous[2:4, 0:2] = (
48 self._shoulder.A_continuous - self._shooter.A_continuous)
49 self.A_continuous[2:4, 2:4] = self._shooter.A_continuous
Austin Schuha88c4072016-02-06 14:31:03 -080050
Tyler Chatow6738c362019-02-16 14:12:30 -080051 self.B_continuous = numpy.matrix(numpy.zeros((4, 2)))
52 self.B_continuous[0:2, 0:1] = self._shoulder.B_continuous
53 self.B_continuous[2:4, 1:2] = self._shooter.B_continuous
54 self.B_continuous[2:4, 0:1] = self._shoulder.B_continuous
Austin Schuha88c4072016-02-06 14:31:03 -080055
Tyler Chatow6738c362019-02-16 14:12:30 -080056 self.C = numpy.matrix(numpy.zeros((2, 4)))
57 self.C[0:1, 0:2] = self._shoulder.C
58 self.C[1:2, 0:2] = -self._shoulder.C
59 self.C[1:2, 2:4] = self._shooter.C
Austin Schuha88c4072016-02-06 14:31:03 -080060
Tyler Chatow6738c362019-02-16 14:12:30 -080061 # D is 0 for all our loops.
62 self.D = numpy.matrix(numpy.zeros((2, 2)))
Austin Schuha88c4072016-02-06 14:31:03 -080063
Tyler Chatow6738c362019-02-16 14:12:30 -080064 self.dt = 0.005
Austin Schuha88c4072016-02-06 14:31:03 -080065
Tyler Chatow6738c362019-02-16 14:12:30 -080066 self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
67 self.B_continuous, self.dt)
Austin Schuha88c4072016-02-06 14:31:03 -080068
Tyler Chatow6738c362019-02-16 14:12:30 -080069 # Cost of error
70 self.Q = numpy.matrix(numpy.zeros((4, 4)))
71 q_pos_shoulder = 0.014
72 q_vel_shoulder = 4.00
73 q_pos_shooter = 0.014
74 q_vel_shooter = 4.00
75 self.Q[0, 0] = 1.0 / q_pos_shoulder**2.0
76 self.Q[1, 1] = 1.0 / q_vel_shoulder**2.0
77 self.Q[2, 2] = 1.0 / q_pos_shooter**2.0
78 self.Q[3, 3] = 1.0 / q_vel_shooter**2.0
Austin Schuh2fc10fa2016-02-08 00:44:34 -080079
Tyler Chatow6738c362019-02-16 14:12:30 -080080 self.Qff = numpy.matrix(numpy.zeros((4, 4)))
81 qff_pos_shoulder = 0.005
82 qff_vel_shoulder = 1.00
83 qff_pos_shooter = 0.005
84 qff_vel_shooter = 1.00
85 self.Qff[0, 0] = 1.0 / qff_pos_shoulder**2.0
86 self.Qff[1, 1] = 1.0 / qff_vel_shoulder**2.0
87 self.Qff[2, 2] = 1.0 / qff_pos_shooter**2.0
88 self.Qff[3, 3] = 1.0 / qff_vel_shooter**2.0
Austin Schuha88c4072016-02-06 14:31:03 -080089
Tyler Chatow6738c362019-02-16 14:12:30 -080090 # Cost of control effort
91 self.R = numpy.matrix(numpy.zeros((2, 2)))
92 r_voltage = 1.0 / 12.0
93 self.R[0, 0] = r_voltage**2.0
94 self.R[1, 1] = r_voltage**2.0
Austin Schuha88c4072016-02-06 14:31:03 -080095
Tyler Chatow6738c362019-02-16 14:12:30 -080096 self.Kff = controls.TwoStateFeedForwards(self.B, self.Qff)
Austin Schuha88c4072016-02-06 14:31:03 -080097
Tyler Chatow6738c362019-02-16 14:12:30 -080098 glog.debug('Shoulder K')
99 glog.debug(repr(self._shoulder.K))
100 glog.debug(
101 'Poles are %s',
102 repr(
103 numpy.linalg.eig(self._shoulder.A -
104 self._shoulder.B * self._shoulder.K)[0]))
Austin Schuha88c4072016-02-06 14:31:03 -0800105
Tyler Chatow6738c362019-02-16 14:12:30 -0800106 # Compute controller gains.
107 # self.K = controls.dlqr(self.A, self.B, self.Q, self.R)
108 self.K = numpy.matrix(numpy.zeros((2, 4)))
109 self.K[0:1, 0:2] = self._shoulder.K
110 self.K[1:2, 0:2] = (
111 -self.Kff[1:2, 2:4] * self.B[2:4, 0:1] * self._shoulder.K +
112 self.Kff[1:2, 2:4] * self.A[2:4, 0:2])
113 self.K[1:2, 2:4] = self._shooter.K
Austin Schuha88c4072016-02-06 14:31:03 -0800114
Tyler Chatow6738c362019-02-16 14:12:30 -0800115 glog.debug('Arm controller %s', repr(self.K))
Austin Schuha88c4072016-02-06 14:31:03 -0800116
Tyler Chatow6738c362019-02-16 14:12:30 -0800117 # Cost of error
118 self.Q = numpy.matrix(numpy.zeros((4, 4)))
119 q_pos_shoulder = 0.05
120 q_vel_shoulder = 2.65
121 q_pos_shooter = 0.05
122 q_vel_shooter = 2.65
123 self.Q[0, 0] = q_pos_shoulder**2.0
124 self.Q[1, 1] = q_vel_shoulder**2.0
125 self.Q[2, 2] = q_pos_shooter**2.0
126 self.Q[3, 3] = q_vel_shooter**2.0
Austin Schuha88c4072016-02-06 14:31:03 -0800127
Tyler Chatow6738c362019-02-16 14:12:30 -0800128 # Cost of control effort
129 self.R = numpy.matrix(numpy.zeros((2, 2)))
130 r_voltage = 0.025
131 self.R[0, 0] = r_voltage**2.0
132 self.R[1, 1] = r_voltage**2.0
Austin Schuha88c4072016-02-06 14:31:03 -0800133
Tyler Chatow6738c362019-02-16 14:12:30 -0800134 self.KalmanGain, self.Q_steady = controls.kalman(
135 A=self.A, B=self.B, C=self.C, Q=self.Q, R=self.R)
136 self.L = self.A * self.KalmanGain
Austin Schuha88c4072016-02-06 14:31:03 -0800137
Tyler Chatow6738c362019-02-16 14:12:30 -0800138 self.U_max = numpy.matrix([[12.0], [12.0]])
139 self.U_min = numpy.matrix([[-12.0], [-12.0]])
140
141 self.InitializeState()
Austin Schuha88c4072016-02-06 14:31:03 -0800142
143
144class IntegralArm(Arm):
Austin Schuha88c4072016-02-06 14:31:03 -0800145
Tyler Chatow6738c362019-02-16 14:12:30 -0800146 def __init__(self, name="IntegralArm", J=None):
147 super(IntegralArm, self).__init__(name=name, J=J)
Austin Schuha88c4072016-02-06 14:31:03 -0800148
Tyler Chatow6738c362019-02-16 14:12:30 -0800149 self.A_continuous_unaugmented = self.A_continuous
150 self.B_continuous_unaugmented = self.B_continuous
Austin Schuha88c4072016-02-06 14:31:03 -0800151
Tyler Chatow6738c362019-02-16 14:12:30 -0800152 self.A_continuous = numpy.matrix(numpy.zeros((6, 6)))
153 self.A_continuous[0:4, 0:4] = self.A_continuous_unaugmented
154 self.A_continuous[0:4, 4:6] = self.B_continuous_unaugmented
Austin Schuha88c4072016-02-06 14:31:03 -0800155
Tyler Chatow6738c362019-02-16 14:12:30 -0800156 self.B_continuous = numpy.matrix(numpy.zeros((6, 2)))
157 self.B_continuous[0:4, 0:2] = self.B_continuous_unaugmented
Austin Schuha88c4072016-02-06 14:31:03 -0800158
Tyler Chatow6738c362019-02-16 14:12:30 -0800159 self.C_unaugmented = self.C
160 self.C = numpy.matrix(numpy.zeros((2, 6)))
161 self.C[0:2, 0:4] = self.C_unaugmented
Austin Schuha88c4072016-02-06 14:31:03 -0800162
Tyler Chatow6738c362019-02-16 14:12:30 -0800163 self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
164 self.B_continuous, self.dt)
Austin Schuha88c4072016-02-06 14:31:03 -0800165
Tyler Chatow6738c362019-02-16 14:12:30 -0800166 q_pos_shoulder = 0.10
167 q_vel_shoulder = 0.005
168 q_voltage_shoulder = 3.5
169 q_pos_shooter = 0.08
170 q_vel_shooter = 2.00
171 q_voltage_shooter = 1.0
172 self.Q = numpy.matrix(numpy.zeros((6, 6)))
173 self.Q[0, 0] = q_pos_shoulder**2.0
174 self.Q[1, 1] = q_vel_shoulder**2.0
175 self.Q[2, 2] = q_pos_shooter**2.0
176 self.Q[3, 3] = q_vel_shooter**2.0
177 self.Q[4, 4] = q_voltage_shoulder**2.0
178 self.Q[5, 5] = q_voltage_shooter**2.0
Austin Schuha88c4072016-02-06 14:31:03 -0800179
Tyler Chatow6738c362019-02-16 14:12:30 -0800180 self.R = numpy.matrix(numpy.zeros((2, 2)))
181 r_pos = 0.05
182 self.R[0, 0] = r_pos**2.0
183 self.R[1, 1] = r_pos**2.0
Austin Schuha88c4072016-02-06 14:31:03 -0800184
Tyler Chatow6738c362019-02-16 14:12:30 -0800185 self.KalmanGain, self.Q_steady = controls.kalman(
186 A=self.A, B=self.B, C=self.C, Q=self.Q, R=self.R)
187 self.L = self.A * self.KalmanGain
Austin Schuha88c4072016-02-06 14:31:03 -0800188
Tyler Chatow6738c362019-02-16 14:12:30 -0800189 self.K_unaugmented = self.K
190 self.K = numpy.matrix(numpy.zeros((2, 6)))
191 self.K[0:2, 0:4] = self.K_unaugmented
192 self.K[0, 4] = 1
193 self.K[1, 5] = 1
Austin Schuha88c4072016-02-06 14:31:03 -0800194
Tyler Chatow6738c362019-02-16 14:12:30 -0800195 self.Kff = numpy.concatenate(
196 (self.Kff, numpy.matrix(numpy.zeros((2, 2)))), axis=1)
197
198 self.InitializeState()
Austin Schuha88c4072016-02-06 14:31:03 -0800199
200
201class ScenarioPlotter(object):
Austin Schuha88c4072016-02-06 14:31:03 -0800202
Tyler Chatow6738c362019-02-16 14:12:30 -0800203 def __init__(self):
204 # Various lists for graphing things.
205 self.t = []
206 self.x_shoulder = []
207 self.v_shoulder = []
208 self.a_shoulder = []
209 self.x_hat_shoulder = []
210 self.u_shoulder = []
211 self.offset_shoulder = []
212 self.x_shooter = []
213 self.v_shooter = []
214 self.a_shooter = []
215 self.x_hat_shooter = []
216 self.u_shooter = []
217 self.offset_shooter = []
218 self.goal_x_shoulder = []
219 self.goal_v_shoulder = []
220 self.goal_x_shooter = []
221 self.goal_v_shooter = []
Austin Schuha88c4072016-02-06 14:31:03 -0800222
Tyler Chatow6738c362019-02-16 14:12:30 -0800223 def run_test(self,
224 arm,
225 end_goal,
226 iterations=200,
227 controller=None,
228 observer=None):
229 """Runs the plant with an initial condition and goal.
Austin Schuha88c4072016-02-06 14:31:03 -0800230
Tyler Chatow6738c362019-02-16 14:12:30 -0800231 Args:
232 arm: Arm object to use.
233 end_goal: numpy.Matrix[6, 1], end goal state.
234 iterations: Number of timesteps to run the model for.
235 controller: Arm object to get K from, or None if we should
236 use arm.
237 observer: Arm object to use for the observer, or None if we should
238 use the actual state.
239 """
Austin Schuha88c4072016-02-06 14:31:03 -0800240
Tyler Chatow6738c362019-02-16 14:12:30 -0800241 if controller is None:
242 controller = arm
Austin Schuha88c4072016-02-06 14:31:03 -0800243
Tyler Chatow6738c362019-02-16 14:12:30 -0800244 vbat = 12.0
Austin Schuha88c4072016-02-06 14:31:03 -0800245
Tyler Chatow6738c362019-02-16 14:12:30 -0800246 if self.t:
247 initial_t = self.t[-1] + arm.dt
248 else:
249 initial_t = 0
Austin Schuha88c4072016-02-06 14:31:03 -0800250
Tyler Chatow6738c362019-02-16 14:12:30 -0800251 goal = numpy.concatenate((arm.X, numpy.matrix(numpy.zeros((2, 1)))),
252 axis=0)
Austin Schuha88c4072016-02-06 14:31:03 -0800253
Tyler Chatow6738c362019-02-16 14:12:30 -0800254 shoulder_profile = TrapezoidProfile(arm.dt)
255 shoulder_profile.set_maximum_acceleration(12.0)
256 shoulder_profile.set_maximum_velocity(10.0)
257 shoulder_profile.SetGoal(goal[0, 0])
258 shooter_profile = TrapezoidProfile(arm.dt)
259 shooter_profile.set_maximum_acceleration(50.0)
260 shooter_profile.set_maximum_velocity(10.0)
261 shooter_profile.SetGoal(goal[2, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800262
Tyler Chatow6738c362019-02-16 14:12:30 -0800263 U_last = numpy.matrix(numpy.zeros((2, 1)))
Austin Schuh5ea48472021-02-02 20:46:41 -0800264 for i in range(iterations):
Tyler Chatow6738c362019-02-16 14:12:30 -0800265 X_hat = arm.X
Austin Schuha88c4072016-02-06 14:31:03 -0800266
Tyler Chatow6738c362019-02-16 14:12:30 -0800267 if observer is not None:
268 observer.Y = arm.Y
269 observer.CorrectObserver(U_last)
270 self.offset_shoulder.append(observer.X_hat[4, 0])
271 self.offset_shooter.append(observer.X_hat[5, 0])
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800272
Tyler Chatow6738c362019-02-16 14:12:30 -0800273 X_hat = observer.X_hat
274 self.x_hat_shoulder.append(observer.X_hat[0, 0])
275 self.x_hat_shooter.append(observer.X_hat[2, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800276
Tyler Chatow6738c362019-02-16 14:12:30 -0800277 next_shoulder_goal = shoulder_profile.Update(
278 end_goal[0, 0], end_goal[1, 0])
279 next_shooter_goal = shooter_profile.Update(end_goal[2, 0],
280 end_goal[3, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800281
Tyler Chatow6738c362019-02-16 14:12:30 -0800282 next_goal = numpy.concatenate(
283 (next_shoulder_goal, next_shooter_goal,
284 numpy.matrix(numpy.zeros((2, 1)))),
285 axis=0)
286 self.goal_x_shoulder.append(goal[0, 0])
287 self.goal_v_shoulder.append(goal[1, 0])
288 self.goal_x_shooter.append(goal[2, 0])
289 self.goal_v_shooter.append(goal[3, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800290
Tyler Chatow6738c362019-02-16 14:12:30 -0800291 ff_U = controller.Kff * (next_goal - observer.A * goal)
Austin Schuha88c4072016-02-06 14:31:03 -0800292
Tyler Chatow6738c362019-02-16 14:12:30 -0800293 U_uncapped = controller.K * (goal - X_hat) + ff_U
294 U = U_uncapped.copy()
Austin Schuha88c4072016-02-06 14:31:03 -0800295
Tyler Chatow6738c362019-02-16 14:12:30 -0800296 U[0, 0] = numpy.clip(U[0, 0], -vbat, vbat)
297 U[1, 0] = numpy.clip(U[1, 0], -vbat, vbat)
298 self.x_shoulder.append(arm.X[0, 0])
299 self.x_shooter.append(arm.X[2, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800300
Tyler Chatow6738c362019-02-16 14:12:30 -0800301 if self.v_shoulder:
302 last_v_shoulder = self.v_shoulder[-1]
303 else:
304 last_v_shoulder = 0
305 self.v_shoulder.append(arm.X[1, 0])
306 self.a_shoulder.append(
307 (self.v_shoulder[-1] - last_v_shoulder) / arm.dt)
Austin Schuha88c4072016-02-06 14:31:03 -0800308
Tyler Chatow6738c362019-02-16 14:12:30 -0800309 if self.v_shooter:
310 last_v_shooter = self.v_shooter[-1]
311 else:
312 last_v_shooter = 0
313 self.v_shooter.append(arm.X[3, 0])
314 self.a_shooter.append(
315 (self.v_shooter[-1] - last_v_shooter) / arm.dt)
Austin Schuha88c4072016-02-06 14:31:03 -0800316
Tyler Chatow6738c362019-02-16 14:12:30 -0800317 if i % 40 == 0:
318 # Test that if we move the shoulder, the shooter stays perfect.
319 #observer.X_hat[0, 0] += 0.20
320 #arm.X[0, 0] += 0.20
321 pass
322 U_error = numpy.matrix([[2.0], [2.0]])
323 # Kick it and see what happens.
324 #if (initial_t + i * arm.dt) % 0.4 > 0.2:
325 #U_error = numpy.matrix([[4.0], [0.0]])
326 #else:
327 #U_error = numpy.matrix([[-4.0], [0.0]])
Austin Schuha88c4072016-02-06 14:31:03 -0800328
Tyler Chatow6738c362019-02-16 14:12:30 -0800329 arm.Update(U + U_error)
Austin Schuha88c4072016-02-06 14:31:03 -0800330
Tyler Chatow6738c362019-02-16 14:12:30 -0800331 if observer is not None:
332 observer.PredictObserver(U)
Austin Schuha88c4072016-02-06 14:31:03 -0800333
Tyler Chatow6738c362019-02-16 14:12:30 -0800334 self.t.append(initial_t + i * arm.dt)
335 self.u_shoulder.append(U[0, 0])
336 self.u_shooter.append(U[1, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800337
Tyler Chatow6738c362019-02-16 14:12:30 -0800338 ff_U -= U_uncapped - U
339 goal = controller.A * goal + controller.B * ff_U
Austin Schuha88c4072016-02-06 14:31:03 -0800340
Tyler Chatow6738c362019-02-16 14:12:30 -0800341 if U[0, 0] != U_uncapped[0, 0]:
342 glog.debug('Moving shoulder %s', repr(initial_t + i * arm.dt))
343 glog.debug('U error %s', repr(U_uncapped - U))
344 glog.debug(
345 'goal change is %s',
346 repr(next_shoulder_goal -
347 numpy.matrix([[goal[0, 0]], [goal[1, 0]]])))
348 shoulder_profile.MoveCurrentState(
349 numpy.matrix([[goal[0, 0]], [goal[1, 0]]]))
350 if U[1, 0] != U_uncapped[1, 0]:
351 glog.debug('Moving shooter %s', repr(initial_t + i * arm.dt))
352 glog.debug('U error %s', repr(U_uncapped - U))
353 shooter_profile.MoveCurrentState(
354 numpy.matrix([[goal[2, 0]], [goal[3, 0]]]))
355 U_last = U
356 glog.debug('goal_error %s', repr(end_goal - goal))
357 glog.debug('error %s', repr(observer.X_hat - end_goal))
Austin Schuha88c4072016-02-06 14:31:03 -0800358
Tyler Chatow6738c362019-02-16 14:12:30 -0800359 def Plot(self):
360 pylab.subplot(3, 1, 1)
361 pylab.plot(self.t, self.x_shoulder, label='x shoulder')
362 pylab.plot(self.t, self.goal_x_shoulder, label='goal x shoulder')
363 pylab.plot(self.t, self.x_hat_shoulder, label='x_hat shoulder')
Austin Schuha88c4072016-02-06 14:31:03 -0800364
Tyler Chatow6738c362019-02-16 14:12:30 -0800365 pylab.plot(self.t, self.x_shooter, label='x shooter')
366 pylab.plot(self.t, self.x_hat_shooter, label='x_hat shooter')
367 pylab.plot(self.t, self.goal_x_shooter, label='goal x shooter')
368 pylab.plot(
369 self.t,
370 map(operator.add, self.x_shooter, self.x_shoulder),
371 label='x shooter ground')
372 pylab.plot(
373 self.t,
374 map(operator.add, self.x_hat_shooter, self.x_hat_shoulder),
375 label='x_hat shooter ground')
376 pylab.legend()
Austin Schuha88c4072016-02-06 14:31:03 -0800377
Tyler Chatow6738c362019-02-16 14:12:30 -0800378 pylab.subplot(3, 1, 2)
379 pylab.plot(self.t, self.u_shoulder, label='u shoulder')
380 pylab.plot(
381 self.t, self.offset_shoulder, label='voltage_offset shoulder')
382 pylab.plot(self.t, self.u_shooter, label='u shooter')
383 pylab.plot(self.t, self.offset_shooter, label='voltage_offset shooter')
384 pylab.legend()
Austin Schuha88c4072016-02-06 14:31:03 -0800385
Tyler Chatow6738c362019-02-16 14:12:30 -0800386 pylab.subplot(3, 1, 3)
387 pylab.plot(self.t, self.a_shoulder, label='a_shoulder')
388 pylab.plot(self.t, self.a_shooter, label='a_shooter')
389 pylab.legend()
Austin Schuha88c4072016-02-06 14:31:03 -0800390
Tyler Chatow6738c362019-02-16 14:12:30 -0800391 pylab.show()
Austin Schuha88c4072016-02-06 14:31:03 -0800392
393
394def main(argv):
Tyler Chatow6738c362019-02-16 14:12:30 -0800395 argv = FLAGS(argv)
396 glog.init()
Austin Schuha88c4072016-02-06 14:31:03 -0800397
Tyler Chatow6738c362019-02-16 14:12:30 -0800398 scenario_plotter = ScenarioPlotter()
Austin Schuha88c4072016-02-06 14:31:03 -0800399
Tyler Chatow6738c362019-02-16 14:12:30 -0800400 J_accelerating = 18
401 J_decelerating = 7
Austin Schuh6ca0f792016-03-12 14:06:14 -0800402
Tyler Chatow6738c362019-02-16 14:12:30 -0800403 arm = Arm(name='AcceleratingArm', J=J_accelerating)
404 arm_integral_controller = IntegralArm(
405 name='AcceleratingIntegralArm', J=J_accelerating)
406 arm_observer = IntegralArm()
Austin Schuha88c4072016-02-06 14:31:03 -0800407
Tyler Chatow6738c362019-02-16 14:12:30 -0800408 # Test moving the shoulder with constant separation.
409 initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0], [0.0], [0.0]])
410 R = numpy.matrix([
411 [numpy.pi / 2.0],
412 [0.0],
413 [0.0], #[numpy.pi / 2.0],
414 [0.0],
415 [0.0],
416 [0.0]
417 ])
418 arm.X = initial_X[0:4, 0]
419 arm_observer.X = initial_X
Austin Schuha88c4072016-02-06 14:31:03 -0800420
Tyler Chatow6738c362019-02-16 14:12:30 -0800421 scenario_plotter.run_test(
422 arm=arm,
423 end_goal=R,
424 iterations=300,
425 controller=arm_integral_controller,
426 observer=arm_observer)
Austin Schuha88c4072016-02-06 14:31:03 -0800427
Tyler Chatow6738c362019-02-16 14:12:30 -0800428 if len(argv) != 5:
429 glog.fatal(
430 'Expected .h file name and .cc file name for the wrist and integral wrist.'
431 )
432 else:
433 namespaces = ['y2016', 'control_loops', 'superstructure']
434 decelerating_arm = Arm(name='DeceleratingArm', J=J_decelerating)
435 loop_writer = control_loop.ControlLoopWriter(
436 'Arm', [arm, decelerating_arm], namespaces=namespaces)
437 loop_writer.Write(argv[1], argv[2])
Austin Schuha88c4072016-02-06 14:31:03 -0800438
Tyler Chatow6738c362019-02-16 14:12:30 -0800439 decelerating_integral_arm_controller = IntegralArm(
440 name='DeceleratingIntegralArm', J=J_decelerating)
Austin Schuh6ca0f792016-03-12 14:06:14 -0800441
Tyler Chatow6738c362019-02-16 14:12:30 -0800442 integral_loop_writer = control_loop.ControlLoopWriter(
443 'IntegralArm',
444 [arm_integral_controller, decelerating_integral_arm_controller],
445 namespaces=namespaces)
446 integral_loop_writer.AddConstant(
447 control_loop.Constant("kV_shoulder", "%f",
448 arm_integral_controller.shoulder_Kv))
449 integral_loop_writer.Write(argv[3], argv[4])
Austin Schuha88c4072016-02-06 14:31:03 -0800450
Tyler Chatow6738c362019-02-16 14:12:30 -0800451 if FLAGS.plot:
452 scenario_plotter.Plot()
453
Austin Schuha88c4072016-02-06 14:31:03 -0800454
455if __name__ == '__main__':
Tyler Chatow6738c362019-02-16 14:12:30 -0800456 sys.exit(main(sys.argv))