blob: 0b5d87c57817ef24aa2515cbb3a651f2f58f12a1 [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
Ravago Jones5127ccc2022-07-31 16:32:45 -070047 self.A_continuous[2:4, 0:2] = (self._shoulder.A_continuous -
48 self._shooter.A_continuous)
Tyler Chatow6738c362019-02-16 14:12:30 -080049 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
Ravago Jones5127ccc2022-07-31 16:32:45 -0700134 self.KalmanGain, self.Q_steady = controls.kalman(A=self.A,
135 B=self.B,
136 C=self.C,
137 Q=self.Q,
138 R=self.R)
Tyler Chatow6738c362019-02-16 14:12:30 -0800139 self.L = self.A * self.KalmanGain
Austin Schuha88c4072016-02-06 14:31:03 -0800140
Tyler Chatow6738c362019-02-16 14:12:30 -0800141 self.U_max = numpy.matrix([[12.0], [12.0]])
142 self.U_min = numpy.matrix([[-12.0], [-12.0]])
143
144 self.InitializeState()
Austin Schuha88c4072016-02-06 14:31:03 -0800145
146
147class IntegralArm(Arm):
Austin Schuha88c4072016-02-06 14:31:03 -0800148
Tyler Chatow6738c362019-02-16 14:12:30 -0800149 def __init__(self, name="IntegralArm", J=None):
150 super(IntegralArm, self).__init__(name=name, J=J)
Austin Schuha88c4072016-02-06 14:31:03 -0800151
Tyler Chatow6738c362019-02-16 14:12:30 -0800152 self.A_continuous_unaugmented = self.A_continuous
153 self.B_continuous_unaugmented = self.B_continuous
Austin Schuha88c4072016-02-06 14:31:03 -0800154
Tyler Chatow6738c362019-02-16 14:12:30 -0800155 self.A_continuous = numpy.matrix(numpy.zeros((6, 6)))
156 self.A_continuous[0:4, 0:4] = self.A_continuous_unaugmented
157 self.A_continuous[0:4, 4:6] = self.B_continuous_unaugmented
Austin Schuha88c4072016-02-06 14:31:03 -0800158
Tyler Chatow6738c362019-02-16 14:12:30 -0800159 self.B_continuous = numpy.matrix(numpy.zeros((6, 2)))
160 self.B_continuous[0:4, 0:2] = self.B_continuous_unaugmented
Austin Schuha88c4072016-02-06 14:31:03 -0800161
Tyler Chatow6738c362019-02-16 14:12:30 -0800162 self.C_unaugmented = self.C
163 self.C = numpy.matrix(numpy.zeros((2, 6)))
164 self.C[0:2, 0:4] = self.C_unaugmented
Austin Schuha88c4072016-02-06 14:31:03 -0800165
Tyler Chatow6738c362019-02-16 14:12:30 -0800166 self.A, self.B = self.ContinuousToDiscrete(self.A_continuous,
167 self.B_continuous, self.dt)
Austin Schuha88c4072016-02-06 14:31:03 -0800168
Tyler Chatow6738c362019-02-16 14:12:30 -0800169 q_pos_shoulder = 0.10
170 q_vel_shoulder = 0.005
171 q_voltage_shoulder = 3.5
172 q_pos_shooter = 0.08
173 q_vel_shooter = 2.00
174 q_voltage_shooter = 1.0
175 self.Q = numpy.matrix(numpy.zeros((6, 6)))
176 self.Q[0, 0] = q_pos_shoulder**2.0
177 self.Q[1, 1] = q_vel_shoulder**2.0
178 self.Q[2, 2] = q_pos_shooter**2.0
179 self.Q[3, 3] = q_vel_shooter**2.0
180 self.Q[4, 4] = q_voltage_shoulder**2.0
181 self.Q[5, 5] = q_voltage_shooter**2.0
Austin Schuha88c4072016-02-06 14:31:03 -0800182
Tyler Chatow6738c362019-02-16 14:12:30 -0800183 self.R = numpy.matrix(numpy.zeros((2, 2)))
184 r_pos = 0.05
185 self.R[0, 0] = r_pos**2.0
186 self.R[1, 1] = r_pos**2.0
Austin Schuha88c4072016-02-06 14:31:03 -0800187
Ravago Jones5127ccc2022-07-31 16:32:45 -0700188 self.KalmanGain, self.Q_steady = controls.kalman(A=self.A,
189 B=self.B,
190 C=self.C,
191 Q=self.Q,
192 R=self.R)
Tyler Chatow6738c362019-02-16 14:12:30 -0800193 self.L = self.A * self.KalmanGain
Austin Schuha88c4072016-02-06 14:31:03 -0800194
Tyler Chatow6738c362019-02-16 14:12:30 -0800195 self.K_unaugmented = self.K
196 self.K = numpy.matrix(numpy.zeros((2, 6)))
197 self.K[0:2, 0:4] = self.K_unaugmented
198 self.K[0, 4] = 1
199 self.K[1, 5] = 1
Austin Schuha88c4072016-02-06 14:31:03 -0800200
Tyler Chatow6738c362019-02-16 14:12:30 -0800201 self.Kff = numpy.concatenate(
202 (self.Kff, numpy.matrix(numpy.zeros((2, 2)))), axis=1)
203
204 self.InitializeState()
Austin Schuha88c4072016-02-06 14:31:03 -0800205
206
207class ScenarioPlotter(object):
Austin Schuha88c4072016-02-06 14:31:03 -0800208
Tyler Chatow6738c362019-02-16 14:12:30 -0800209 def __init__(self):
210 # Various lists for graphing things.
211 self.t = []
212 self.x_shoulder = []
213 self.v_shoulder = []
214 self.a_shoulder = []
215 self.x_hat_shoulder = []
216 self.u_shoulder = []
217 self.offset_shoulder = []
218 self.x_shooter = []
219 self.v_shooter = []
220 self.a_shooter = []
221 self.x_hat_shooter = []
222 self.u_shooter = []
223 self.offset_shooter = []
224 self.goal_x_shoulder = []
225 self.goal_v_shoulder = []
226 self.goal_x_shooter = []
227 self.goal_v_shooter = []
Austin Schuha88c4072016-02-06 14:31:03 -0800228
Tyler Chatow6738c362019-02-16 14:12:30 -0800229 def run_test(self,
230 arm,
231 end_goal,
232 iterations=200,
233 controller=None,
234 observer=None):
235 """Runs the plant with an initial condition and goal.
Austin Schuha88c4072016-02-06 14:31:03 -0800236
Tyler Chatow6738c362019-02-16 14:12:30 -0800237 Args:
238 arm: Arm object to use.
239 end_goal: numpy.Matrix[6, 1], end goal state.
240 iterations: Number of timesteps to run the model for.
241 controller: Arm object to get K from, or None if we should
242 use arm.
243 observer: Arm object to use for the observer, or None if we should
244 use the actual state.
245 """
Austin Schuha88c4072016-02-06 14:31:03 -0800246
Tyler Chatow6738c362019-02-16 14:12:30 -0800247 if controller is None:
248 controller = arm
Austin Schuha88c4072016-02-06 14:31:03 -0800249
Tyler Chatow6738c362019-02-16 14:12:30 -0800250 vbat = 12.0
Austin Schuha88c4072016-02-06 14:31:03 -0800251
Tyler Chatow6738c362019-02-16 14:12:30 -0800252 if self.t:
253 initial_t = self.t[-1] + arm.dt
254 else:
255 initial_t = 0
Austin Schuha88c4072016-02-06 14:31:03 -0800256
Tyler Chatow6738c362019-02-16 14:12:30 -0800257 goal = numpy.concatenate((arm.X, numpy.matrix(numpy.zeros((2, 1)))),
258 axis=0)
Austin Schuha88c4072016-02-06 14:31:03 -0800259
Tyler Chatow6738c362019-02-16 14:12:30 -0800260 shoulder_profile = TrapezoidProfile(arm.dt)
261 shoulder_profile.set_maximum_acceleration(12.0)
262 shoulder_profile.set_maximum_velocity(10.0)
263 shoulder_profile.SetGoal(goal[0, 0])
264 shooter_profile = TrapezoidProfile(arm.dt)
265 shooter_profile.set_maximum_acceleration(50.0)
266 shooter_profile.set_maximum_velocity(10.0)
267 shooter_profile.SetGoal(goal[2, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800268
Tyler Chatow6738c362019-02-16 14:12:30 -0800269 U_last = numpy.matrix(numpy.zeros((2, 1)))
Austin Schuh5ea48472021-02-02 20:46:41 -0800270 for i in range(iterations):
Tyler Chatow6738c362019-02-16 14:12:30 -0800271 X_hat = arm.X
Austin Schuha88c4072016-02-06 14:31:03 -0800272
Tyler Chatow6738c362019-02-16 14:12:30 -0800273 if observer is not None:
274 observer.Y = arm.Y
275 observer.CorrectObserver(U_last)
276 self.offset_shoulder.append(observer.X_hat[4, 0])
277 self.offset_shooter.append(observer.X_hat[5, 0])
Austin Schuh2fc10fa2016-02-08 00:44:34 -0800278
Tyler Chatow6738c362019-02-16 14:12:30 -0800279 X_hat = observer.X_hat
280 self.x_hat_shoulder.append(observer.X_hat[0, 0])
281 self.x_hat_shooter.append(observer.X_hat[2, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800282
Tyler Chatow6738c362019-02-16 14:12:30 -0800283 next_shoulder_goal = shoulder_profile.Update(
284 end_goal[0, 0], end_goal[1, 0])
285 next_shooter_goal = shooter_profile.Update(end_goal[2, 0],
286 end_goal[3, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800287
Tyler Chatow6738c362019-02-16 14:12:30 -0800288 next_goal = numpy.concatenate(
289 (next_shoulder_goal, next_shooter_goal,
290 numpy.matrix(numpy.zeros((2, 1)))),
291 axis=0)
292 self.goal_x_shoulder.append(goal[0, 0])
293 self.goal_v_shoulder.append(goal[1, 0])
294 self.goal_x_shooter.append(goal[2, 0])
295 self.goal_v_shooter.append(goal[3, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800296
Tyler Chatow6738c362019-02-16 14:12:30 -0800297 ff_U = controller.Kff * (next_goal - observer.A * goal)
Austin Schuha88c4072016-02-06 14:31:03 -0800298
Tyler Chatow6738c362019-02-16 14:12:30 -0800299 U_uncapped = controller.K * (goal - X_hat) + ff_U
300 U = U_uncapped.copy()
Austin Schuha88c4072016-02-06 14:31:03 -0800301
Tyler Chatow6738c362019-02-16 14:12:30 -0800302 U[0, 0] = numpy.clip(U[0, 0], -vbat, vbat)
303 U[1, 0] = numpy.clip(U[1, 0], -vbat, vbat)
304 self.x_shoulder.append(arm.X[0, 0])
305 self.x_shooter.append(arm.X[2, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800306
Tyler Chatow6738c362019-02-16 14:12:30 -0800307 if self.v_shoulder:
308 last_v_shoulder = self.v_shoulder[-1]
309 else:
310 last_v_shoulder = 0
311 self.v_shoulder.append(arm.X[1, 0])
312 self.a_shoulder.append(
313 (self.v_shoulder[-1] - last_v_shoulder) / arm.dt)
Austin Schuha88c4072016-02-06 14:31:03 -0800314
Tyler Chatow6738c362019-02-16 14:12:30 -0800315 if self.v_shooter:
316 last_v_shooter = self.v_shooter[-1]
317 else:
318 last_v_shooter = 0
319 self.v_shooter.append(arm.X[3, 0])
320 self.a_shooter.append(
321 (self.v_shooter[-1] - last_v_shooter) / arm.dt)
Austin Schuha88c4072016-02-06 14:31:03 -0800322
Tyler Chatow6738c362019-02-16 14:12:30 -0800323 if i % 40 == 0:
324 # Test that if we move the shoulder, the shooter stays perfect.
325 #observer.X_hat[0, 0] += 0.20
326 #arm.X[0, 0] += 0.20
327 pass
328 U_error = numpy.matrix([[2.0], [2.0]])
329 # Kick it and see what happens.
330 #if (initial_t + i * arm.dt) % 0.4 > 0.2:
331 #U_error = numpy.matrix([[4.0], [0.0]])
332 #else:
333 #U_error = numpy.matrix([[-4.0], [0.0]])
Austin Schuha88c4072016-02-06 14:31:03 -0800334
Tyler Chatow6738c362019-02-16 14:12:30 -0800335 arm.Update(U + U_error)
Austin Schuha88c4072016-02-06 14:31:03 -0800336
Tyler Chatow6738c362019-02-16 14:12:30 -0800337 if observer is not None:
338 observer.PredictObserver(U)
Austin Schuha88c4072016-02-06 14:31:03 -0800339
Tyler Chatow6738c362019-02-16 14:12:30 -0800340 self.t.append(initial_t + i * arm.dt)
341 self.u_shoulder.append(U[0, 0])
342 self.u_shooter.append(U[1, 0])
Austin Schuha88c4072016-02-06 14:31:03 -0800343
Tyler Chatow6738c362019-02-16 14:12:30 -0800344 ff_U -= U_uncapped - U
345 goal = controller.A * goal + controller.B * ff_U
Austin Schuha88c4072016-02-06 14:31:03 -0800346
Tyler Chatow6738c362019-02-16 14:12:30 -0800347 if U[0, 0] != U_uncapped[0, 0]:
348 glog.debug('Moving shoulder %s', repr(initial_t + i * arm.dt))
349 glog.debug('U error %s', repr(U_uncapped - U))
350 glog.debug(
351 'goal change is %s',
352 repr(next_shoulder_goal -
353 numpy.matrix([[goal[0, 0]], [goal[1, 0]]])))
354 shoulder_profile.MoveCurrentState(
355 numpy.matrix([[goal[0, 0]], [goal[1, 0]]]))
356 if U[1, 0] != U_uncapped[1, 0]:
357 glog.debug('Moving shooter %s', repr(initial_t + i * arm.dt))
358 glog.debug('U error %s', repr(U_uncapped - U))
359 shooter_profile.MoveCurrentState(
360 numpy.matrix([[goal[2, 0]], [goal[3, 0]]]))
361 U_last = U
362 glog.debug('goal_error %s', repr(end_goal - goal))
363 glog.debug('error %s', repr(observer.X_hat - end_goal))
Austin Schuha88c4072016-02-06 14:31:03 -0800364
Tyler Chatow6738c362019-02-16 14:12:30 -0800365 def Plot(self):
366 pylab.subplot(3, 1, 1)
367 pylab.plot(self.t, self.x_shoulder, label='x shoulder')
368 pylab.plot(self.t, self.goal_x_shoulder, label='goal x shoulder')
369 pylab.plot(self.t, self.x_hat_shoulder, label='x_hat shoulder')
Austin Schuha88c4072016-02-06 14:31:03 -0800370
Tyler Chatow6738c362019-02-16 14:12:30 -0800371 pylab.plot(self.t, self.x_shooter, label='x shooter')
372 pylab.plot(self.t, self.x_hat_shooter, label='x_hat shooter')
373 pylab.plot(self.t, self.goal_x_shooter, label='goal x shooter')
Ravago Jones5127ccc2022-07-31 16:32:45 -0700374 pylab.plot(self.t,
375 map(operator.add, self.x_shooter, self.x_shoulder),
376 label='x shooter ground')
377 pylab.plot(self.t,
378 map(operator.add, self.x_hat_shooter, self.x_hat_shoulder),
379 label='x_hat shooter ground')
Tyler Chatow6738c362019-02-16 14:12:30 -0800380 pylab.legend()
Austin Schuha88c4072016-02-06 14:31:03 -0800381
Tyler Chatow6738c362019-02-16 14:12:30 -0800382 pylab.subplot(3, 1, 2)
383 pylab.plot(self.t, self.u_shoulder, label='u shoulder')
Ravago Jones5127ccc2022-07-31 16:32:45 -0700384 pylab.plot(self.t,
385 self.offset_shoulder,
386 label='voltage_offset shoulder')
Tyler Chatow6738c362019-02-16 14:12:30 -0800387 pylab.plot(self.t, self.u_shooter, label='u shooter')
388 pylab.plot(self.t, self.offset_shooter, label='voltage_offset shooter')
389 pylab.legend()
Austin Schuha88c4072016-02-06 14:31:03 -0800390
Tyler Chatow6738c362019-02-16 14:12:30 -0800391 pylab.subplot(3, 1, 3)
392 pylab.plot(self.t, self.a_shoulder, label='a_shoulder')
393 pylab.plot(self.t, self.a_shooter, label='a_shooter')
394 pylab.legend()
Austin Schuha88c4072016-02-06 14:31:03 -0800395
Tyler Chatow6738c362019-02-16 14:12:30 -0800396 pylab.show()
Austin Schuha88c4072016-02-06 14:31:03 -0800397
398
399def main(argv):
Tyler Chatow6738c362019-02-16 14:12:30 -0800400 argv = FLAGS(argv)
401 glog.init()
Austin Schuha88c4072016-02-06 14:31:03 -0800402
Tyler Chatow6738c362019-02-16 14:12:30 -0800403 scenario_plotter = ScenarioPlotter()
Austin Schuha88c4072016-02-06 14:31:03 -0800404
Tyler Chatow6738c362019-02-16 14:12:30 -0800405 J_accelerating = 18
406 J_decelerating = 7
Austin Schuh6ca0f792016-03-12 14:06:14 -0800407
Tyler Chatow6738c362019-02-16 14:12:30 -0800408 arm = Arm(name='AcceleratingArm', J=J_accelerating)
Ravago Jones5127ccc2022-07-31 16:32:45 -0700409 arm_integral_controller = IntegralArm(name='AcceleratingIntegralArm',
410 J=J_accelerating)
Tyler Chatow6738c362019-02-16 14:12:30 -0800411 arm_observer = IntegralArm()
Austin Schuha88c4072016-02-06 14:31:03 -0800412
Tyler Chatow6738c362019-02-16 14:12:30 -0800413 # Test moving the shoulder with constant separation.
414 initial_X = numpy.matrix([[0.0], [0.0], [0.0], [0.0], [0.0], [0.0]])
415 R = numpy.matrix([
416 [numpy.pi / 2.0],
417 [0.0],
418 [0.0], #[numpy.pi / 2.0],
419 [0.0],
420 [0.0],
421 [0.0]
422 ])
423 arm.X = initial_X[0:4, 0]
424 arm_observer.X = initial_X
Austin Schuha88c4072016-02-06 14:31:03 -0800425
Ravago Jones5127ccc2022-07-31 16:32:45 -0700426 scenario_plotter.run_test(arm=arm,
427 end_goal=R,
428 iterations=300,
429 controller=arm_integral_controller,
430 observer=arm_observer)
Austin Schuha88c4072016-02-06 14:31:03 -0800431
Tyler Chatow6738c362019-02-16 14:12:30 -0800432 if len(argv) != 5:
433 glog.fatal(
434 'Expected .h file name and .cc file name for the wrist and integral wrist.'
435 )
436 else:
437 namespaces = ['y2016', 'control_loops', 'superstructure']
438 decelerating_arm = Arm(name='DeceleratingArm', J=J_decelerating)
Ravago Jones5127ccc2022-07-31 16:32:45 -0700439 loop_writer = control_loop.ControlLoopWriter('Arm',
440 [arm, decelerating_arm],
441 namespaces=namespaces)
Tyler Chatow6738c362019-02-16 14:12:30 -0800442 loop_writer.Write(argv[1], argv[2])
Austin Schuha88c4072016-02-06 14:31:03 -0800443
Tyler Chatow6738c362019-02-16 14:12:30 -0800444 decelerating_integral_arm_controller = IntegralArm(
445 name='DeceleratingIntegralArm', J=J_decelerating)
Austin Schuh6ca0f792016-03-12 14:06:14 -0800446
Tyler Chatow6738c362019-02-16 14:12:30 -0800447 integral_loop_writer = control_loop.ControlLoopWriter(
448 'IntegralArm',
449 [arm_integral_controller, decelerating_integral_arm_controller],
450 namespaces=namespaces)
451 integral_loop_writer.AddConstant(
452 control_loop.Constant("kV_shoulder", "%f",
453 arm_integral_controller.shoulder_Kv))
454 integral_loop_writer.Write(argv[3], argv[4])
Austin Schuha88c4072016-02-06 14:31:03 -0800455
Tyler Chatow6738c362019-02-16 14:12:30 -0800456 if FLAGS.plot:
457 scenario_plotter.Plot()
458
Austin Schuha88c4072016-02-06 14:31:03 -0800459
460if __name__ == '__main__':
Tyler Chatow6738c362019-02-16 14:12:30 -0800461 sys.exit(main(sys.argv))