blob: 04983d43d69613fb224e35cce4e380d68a1c34b5 [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):
justinT2162d9bde2024-09-21 17:02:15 -070013 self.swerve_physics = utils.wrap(python_module.swerve_full_dynamics)
justinT2107d41ed2024-07-31 21:12:31 -070014 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):
justinT2162d9bde2024-09-21 17:02:15 -0700105 x_goal = numpy.zeros(16)
justinT2107d41ed2024-07-31 21:12:31 -0700106
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)
justinT21d18f79f2024-09-22 19:43:05 -0700185
186 U_control = numpy.zeros((8, 1))
187
188 for i in range(numpy.shape(result.t)[0]):
189 U_control = numpy.hstack((
190 U_control,
191 numpy.reshape(
192 calc_I(result.t[i], result.y[:, i]),
193 (8, 1),
194 ),
195 ))
196
197 U_control = numpy.delete(U_control, 0, 1)
198
justinT2107d41ed2024-07-31 21:12:31 -0700199 for i in range(xdot.shape[1]):
justinT21d18f79f2024-09-22 19:43:05 -0700200 xdot[:, i] = self.swerve_physics(result.y[:, i],
201 U_control[:, i])[:, 0]
justinT2107d41ed2024-07-31 21:12:31 -0700202
203 for i in range(2):
204 print(f"For t {i * 0.005}")
justinT21d18f79f2024-09-22 19:43:05 -0700205 self.print_state(self.swerve_physics, U_control[:, i], result.y[:,
206 i])
justinT2107d41ed2024-07-31 21:12:31 -0700207
208 def ev(fn, Y):
209 return [fn(Y[:, i], self.I)[0, 0] for i in range(Y.shape[1])]
210
211 fig, axs = pylab.subplots(2)
212 axs[0].plot(result.t, result.y[0, :], label="steer0")
213 axs[0].plot(result.t, result.y[4, :], label="steer1")
214 axs[0].plot(result.t, result.y[8, :], label="steer2")
215 axs[0].plot(result.t, result.y[12, :], label="steer3")
216 axs[0].legend()
217 axs[1].plot(result.t, result.y[2, :], label="steer_velocity0")
218 axs[1].plot(result.t, result.y[6, :], label="steer_velocity1")
219 axs[1].plot(result.t, result.y[10, :], label="steer_velocity2")
220 axs[1].plot(result.t, result.y[14, :], label="steer_velocity3")
221 axs[1].legend()
222
223 fig, axs = pylab.subplots(2)
224 for i in range(len(axs)):
225 axs[i].plot(result.t,
226 ev(self.slip_angle[i], result.y),
227 label=f"slip_angle{i}")
228 axs[i].plot(result.t,
229 ev(self.slip_ratio[i], result.y),
230 label=f"slip_ratio{i}")
231 axs[i].plot(result.t,
232 xdot[2 + i * 4, :],
233 label=f'steering_accel{i}')
234 axs[i].legend()
235
justinT21d18f79f2024-09-22 19:43:05 -0700236 fig, axs = pylab.subplots(4)
justinT2107d41ed2024-07-31 21:12:31 -0700237 axs[0].plot(result.t, result.y[3, :], label="drive_velocity0")
238 axs[0].plot(result.t, result.y[7, :], label="drive_velocity1")
239 axs[0].plot(result.t, result.y[11, :], label="drive_velocity2")
240 axs[0].plot(result.t, result.y[15, :], label="drive_velocity3")
241 axs[0].legend()
242
243 axs[1].plot(result.t, result.y[20, :], label="vy")
244 axs[1].plot(result.t, result.y[21, :], label="omega")
justinT21d18f79f2024-09-22 19:43:05 -0700245 axs[1].plot(result.t, result.y[18, :], label="theta")
justinT2107d41ed2024-07-31 21:12:31 -0700246 axs[1].plot(result.t, xdot[20, :], label="ay")
247 axs[1].plot(result.t, xdot[21, :], label="alpha")
248 axs[1].legend()
249
250 axs[2].plot(result.t, result.y[19, :], label="vx")
251 axs[2].plot(result.t, xdot[19, :], label="ax")
252
253 axs[2].plot(result.t,
254 numpy.hypot(result.y[19, :], result.y[20, :]),
255 label="speed")
256 axs[2].legend()
257
258 pylab.figure()
justinT2107d41ed2024-07-31 21:12:31 -0700259
260 pylab.plot(result.t, U_control[0, :], label="Is0")
261 pylab.plot(result.t, U_control[1, :], label="Id0")
262 pylab.legend()
263
justinT21d18f79f2024-09-22 19:43:05 -0700264 F_plot = numpy.array([
265 self.F[0](result.y[:, i], U_control[:, i])
266 for i in range(result.y[0, :].size)
267 ])
268 axs[3].plot(result.t, F_plot[:, 0], label="force_x0")
269 axs[3].plot(result.t, F_plot[:, 1], label="force_y0")
270 axs[3].legend()
271
justinT2107d41ed2024-07-31 21:12:31 -0700272 pylab.show()
273
274
275if __name__ == "__main__":
276 debug = PhysicsDebug()
277 debug.plot()