blob: db9ea8580c072346bf9c43af851668c1e021ea3f [file] [log] [blame]
justinT2107d41ed2024-07-31 21:12:31 -07001#!/usr/bin/python3
2
3import numpy, scipy
4
5from matplotlib import pylab
6from frc971.control_loops.swerve import physics_test_utils as utils
7from frc971.control_loops.swerve import dynamics
8
9
10class PhysicsDebug(object):
11
12 def wrap(self, python_module):
13 self.swerve_physics = utils.wrap(python_module.swerve_physics)
14 self.contact_patch_velocity = [
15 utils.wrap_module(python_module.contact_patch_velocity, i)
16 for i in range(4)
17 ]
18 self.wheel_ground_velocity = [
19 utils.wrap_module(python_module.wheel_ground_velocity, i)
20 for i in range(4)
21 ]
22 self.wheel_slip_velocity = [
23 utils.wrap_module(python_module.wheel_slip_velocity, i)
24 for i in range(4)
25 ]
26 self.wheel_force = [
27 utils.wrap_module(python_module.wheel_force, i) for i in range(4)
28 ]
29 self.module_angular_accel = [
30 utils.wrap_module(python_module.module_angular_accel, i)
31 for i in range(4)
32 ]
33 self.F = [utils.wrap_module(python_module.F, i) for i in range(4)]
34 self.mounting_location = [
35 utils.wrap_module(python_module.mounting_location, i)
36 for i in range(4)
37 ]
38
39 self.slip_angle = [
40 utils.wrap_module(python_module.slip_angle, i) for i in range(4)
41 ]
42 self.slip_ratio = [
43 utils.wrap_module(python_module.slip_ratio, i) for i in range(4)
44 ]
45 self.Ms = [utils.wrap_module(python_module.Ms, i) for i in range(4)]
46
47 def print_state(self, swerve_physics, I, x):
48 xdot = swerve_physics(x, I)
49
50 for i in range(4):
51 print(f" Slip Angle {i} {self.slip_angle[0](x, I)}")
52 print(f" Slip Ratio {i} {self.slip_ratio[0](x, I)}")
53
54 print(" Steering angle0", x[0])
55 print(" Steering angle1", x[4])
56 print(" Steering angle2", x[8])
57 print(" Steering angle3", x[12])
58 print(" Steering velocity0", xdot[0])
59 print(" Steering velocity1", xdot[4])
60 print(" Steering velocity2", xdot[8])
61 print(" Steering velocity3", xdot[12])
62 print(" Steering accel0", xdot[2])
63 print(" Steering accel1", xdot[6])
64 print(" Steering accel2", xdot[10])
65 print(" Steering accel3", xdot[14])
66 print(" Drive accel0", xdot[3])
67 print(" Drive accel1", xdot[7])
68 print(" Drive accel2", xdot[11])
69 print(" Drive accel3", xdot[15])
70 print(" Drive velocity0", x[3] * 2 * 0.0254)
71 print(" Drive velocity1", x[7] * 2 * 0.0254)
72 print(" Drive velocity2", x[11] * 2 * 0.0254)
73 print(" Drive velocity3", x[15] * 2 * 0.0254)
74 print(" Theta ", x[18])
75 print(" Omega ", x[21])
76 print(" Alpha", xdot[21])
77 print(" vx", xdot[16])
78 print(" vy", xdot[17])
79 print(" ax", xdot[19])
80 print(" ay", xdot[20])
81 print(" Fdx ", x[22])
82 print(" Fdy ", x[23])
83 print(" Moment_d", xdot[24])
84
85 def plot(self):
86 velocity = numpy.array([[1.0], [0.0]])
87
88 flip = False
89 if flip:
90 module_angles = [0.01 + numpy.pi] * 4
91 else:
92 module_angles = [-0.1, -0.1, 0.1, 0.1]
93
94 X = utils.state_vector(
95 velocity=velocity,
96 drive_wheel_velocity=-1.0 if flip else 1.0,
97 omega=0.0,
98 module_angles=module_angles,
99 )
100
101 self.I = numpy.array([[40.0], [0.0], [40.0], [0.0], [40.0], [0.0],
102 [40.0], [0.0]])
103
104 def calc_I(t, x):
105 x_goal = numpy.zeros((16, 1))
106
107 Kp_steer = 15.0
108 Kp_drive = 0.0
109 Kd_steer = 7.0
110 Kd_drive = 0.0
111 Idrive = 5.0 if t < 5.0 else 15.0
112
113 return numpy.array([
114 [
115 Kd_steer * (x_goal[2] - x[2]) + Kp_steer *
116 (x_goal[0] - x[0])
117 ],
118 [Idrive],
119 [
120 Kd_steer * (x_goal[6] - x[6]) + Kp_steer *
121 (x_goal[4] - x[4])
122 ],
123 [Idrive],
124 [
125 Kd_steer * (x_goal[10] - x[10]) + Kp_steer *
126 (x_goal[8] - x[8])
127 ],
128 [Idrive],
129 [
130 Kd_steer * (x_goal[14] - x[14]) + Kp_steer *
131 (x_goal[12] - x[12])
132 ],
133 [Idrive],
134 ]).flatten()
135 return numpy.array([
136 [
137 Kd_steer * (x_goal[2] - x[2]) + Kp_steer *
138 (x_goal[0] - x[0])
139 ],
140 [
141 Kd_drive * (x_goal[3] - x[3]) + Kp_drive *
142 (x_goal[1] - x[1])
143 ],
144 [
145 Kd_steer * (x_goal[6] - x[6]) + Kp_steer *
146 (x_goal[4] - x[4])
147 ],
148 [
149 Kd_drive * (x_goal[7] - x[7]) + Kp_drive *
150 (x_goal[5] - x[5])
151 ],
152 [
153 Kd_steer * (x_goal[10] - x[10]) + Kp_steer *
154 (x_goal[8] - x[8])
155 ],
156 [
157 Kd_drive * (x_goal[11] - x[11]) + Kp_drive *
158 (x_goal[9] - x[9])
159 ],
160 [
161 Kd_steer * (x_goal[14] - x[14]) + Kp_steer *
162 (x_goal[12] - x[12])
163 ],
164 [
165 Kd_drive * (x_goal[15] - x[15]) + Kp_drive *
166 (x_goal[13] - x[13])
167 ],
168 ]).flatten()
169
170 t_eval = numpy.arange(0, 10.0, 0.005)
171 self.wrap(dynamics)
172 result = scipy.integrate.solve_ivp(
173 lambda t, x: self.swerve_physics(x, calc_I(t, x)).flatten(),
174 [0, t_eval[-1]],
175 X.flatten(),
176 t_eval=t_eval,
177 )
178 print("Function evaluations", result.nfev)
179
180 # continue
181 print(result.y.shape)
182 print(result.t.shape)
183 xdot = numpy.zeros(result.y.shape)
184 print("shape", xdot.shape)
185 for i in range(xdot.shape[1]):
186 xdot[:, i] = self.swerve_physics(result.y[:, i], self.I)[:, 0]
187
188 for i in range(2):
189 print(f"For t {i * 0.005}")
190 self.print_state(self.swerve_physics, self.I, result.y[:, i])
191
192 def ev(fn, Y):
193 return [fn(Y[:, i], self.I)[0, 0] for i in range(Y.shape[1])]
194
195 fig, axs = pylab.subplots(2)
196 axs[0].plot(result.t, result.y[0, :], label="steer0")
197 axs[0].plot(result.t, result.y[4, :], label="steer1")
198 axs[0].plot(result.t, result.y[8, :], label="steer2")
199 axs[0].plot(result.t, result.y[12, :], label="steer3")
200 axs[0].legend()
201 axs[1].plot(result.t, result.y[2, :], label="steer_velocity0")
202 axs[1].plot(result.t, result.y[6, :], label="steer_velocity1")
203 axs[1].plot(result.t, result.y[10, :], label="steer_velocity2")
204 axs[1].plot(result.t, result.y[14, :], label="steer_velocity3")
205 axs[1].legend()
206
207 fig, axs = pylab.subplots(2)
208 for i in range(len(axs)):
209 axs[i].plot(result.t,
210 ev(self.slip_angle[i], result.y),
211 label=f"slip_angle{i}")
212 axs[i].plot(result.t,
213 ev(self.slip_ratio[i], result.y),
214 label=f"slip_ratio{i}")
215 axs[i].plot(result.t,
216 xdot[2 + i * 4, :],
217 label=f'steering_accel{i}')
218 axs[i].legend()
219
220 fig, axs = pylab.subplots(3)
221 axs[0].plot(result.t, result.y[3, :], label="drive_velocity0")
222 axs[0].plot(result.t, result.y[7, :], label="drive_velocity1")
223 axs[0].plot(result.t, result.y[11, :], label="drive_velocity2")
224 axs[0].plot(result.t, result.y[15, :], label="drive_velocity3")
225 axs[0].legend()
226
227 axs[1].plot(result.t, result.y[20, :], label="vy")
228 axs[1].plot(result.t, result.y[21, :], label="omega")
229 axs[1].plot(result.t, xdot[20, :], label="ay")
230 axs[1].plot(result.t, xdot[21, :], label="alpha")
231 axs[1].legend()
232
233 axs[2].plot(result.t, result.y[19, :], label="vx")
234 axs[2].plot(result.t, xdot[19, :], label="ax")
235
236 axs[2].plot(result.t,
237 numpy.hypot(result.y[19, :], result.y[20, :]),
238 label="speed")
239 axs[2].legend()
240
241 pylab.figure()
242 U_control = numpy.zeros((8, 1))
243
244 for i in range(numpy.shape(result.t)[0]):
245 U_control = numpy.hstack((
246 U_control,
247 numpy.reshape(
248 calc_I(result.t[i], numpy.reshape(result.y[:, i],
249 (25, 1))),
250 (8, 1),
251 ),
252 ))
253
254 U_control = numpy.delete(U_control, 0, 1)
255
256 pylab.plot(result.t, U_control[0, :], label="Is0")
257 pylab.plot(result.t, U_control[1, :], label="Id0")
258 pylab.legend()
259
260 pylab.show()
261
262
263if __name__ == "__main__":
264 debug = PhysicsDebug()
265 debug.plot()