blob: 6538ec8beffdf35f7114c28e794b5518994c2a0d [file] [log] [blame]
James Kuszmaulc4ae11c2020-12-26 16:26:58 -08001// Provides a plot for debugging drivetrain-related issues.
2import {AosPlotter} from 'org_frc971/aos/network/www/aos_plotter';
3import {ImuMessageHandler} from 'org_frc971/frc971/wpilib/imu_plot_utils';
4import * as proxy from 'org_frc971/aos/network/www/proxy';
5
6import Connection = proxy.Connection;
7
8const kRed = [1, 0, 0];
9const kGreen = [0, 1, 0];
10const kBlue = [0, 0, 1];
11const kBrown = [0.6, 0.3, 0];
12const kPink = [1, 0.3, 1];
13const kCyan = [0.3, 1, 1];
14const kWhite = [1, 1, 1];
15
16export function plotDrivetrain(conn: Connection, element: Element): void {
17 const width = 900;
18 const height = 400;
19 const aosPlotter = new AosPlotter(conn);
20
21 const joystickState = aosPlotter.addMessageSource('/aos', 'aos.JoystickState');
22 const robotState = aosPlotter.addMessageSource('/aos', 'aos.RobotState');
23 const goal = aosPlotter.addMessageSource('/drivetrain', 'frc971.control_loops.drivetrain.Goal');
24 const status = aosPlotter.addMessageSource(
25 '/drivetrain', 'frc971.control_loops.drivetrain.Status');
26 const output = aosPlotter.addMessageSource(
27 '/drivetrain', 'frc971.control_loops.drivetrain.Output');
28 const imu = aosPlotter.addRawMessageSource(
29 '/drivetrain', 'frc971.IMUValuesBatch',
30 new ImuMessageHandler(conn.getSchema('frc971.IMUValuesBatch')));
31
32 let currentTop = 0;
33
34 // Robot Enabled/Disabled and Mode
35 const robotStatePlot =
36 aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
37 currentTop += height / 2;
38 robotStatePlot.plot.getAxisLabels().setTitle('Robot State');
39 robotStatePlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
40 robotStatePlot.plot.getAxisLabels().setYLabel('bool');
41 robotStatePlot.plot.setDefaultYRange([-0.1, 1.1]);
42
43 const testMode = robotStatePlot.addMessageLine(joystickState, ['test_mode']);
44 testMode.setColor(kBlue);
45 testMode.setPointSize(0.0);
46 const autoMode = robotStatePlot.addMessageLine(joystickState, ['autonomous']);
47 autoMode.setColor(kRed);
48 autoMode.setPointSize(0.0);
49
50 const brownOut = robotStatePlot.addMessageLine(robotState, ['browned_out']);
51 brownOut.setColor(kBrown);
52 brownOut.setDrawLine(false);
53 const enabled = robotStatePlot.addMessageLine(joystickState, ['enabled']);
54 enabled.setColor(kGreen);
55 enabled.setDrawLine(false);
56
57 // Battery Voltage
58 const batteryPlot =
59 aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
60 currentTop += height / 2;
61 batteryPlot.plot.getAxisLabels().setTitle('Battery Voltage');
62 batteryPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
63 batteryPlot.plot.getAxisLabels().setYLabel('Voltage (V)');
64
65 batteryPlot.addMessageLine(robotState, ['voltage_battery']);
66
67 // Polydrivetrain (teleop control) plots
68 const teleopPlot =
69 aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
70 currentTop += height / 2;
71 teleopPlot.plot.getAxisLabels().setTitle('Drivetrain Teleop Goals');
72 teleopPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
73 teleopPlot.plot.getAxisLabels().setYLabel('bool, throttle/wheel values');
74 teleopPlot.plot.setDefaultYRange([-1.1, 1.1]);
75
76 const quickTurn = teleopPlot.addMessageLine(goal, ['quickturn']);
77 quickTurn.setColor(kRed);
78 const throttle = teleopPlot.addMessageLine(goal, ['throttle']);
79 throttle.setColor(kGreen);
80 const wheel = teleopPlot.addMessageLine(goal, ['wheel']);
81 wheel.setColor(kBlue);
82
83 // Drivetrain Control Mode
84 const modePlot =
85 aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
86 currentTop += height / 2;
87 // TODO(james): Actually add enum support.
88 modePlot.plot.getAxisLabels().setTitle(
89 'Drivetrain Mode [POLYDRIVE, MOTION_PROFILE, ' +
90 'SPLINE_FOLLOWER, LINE_FOLLOWER]');
91 modePlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
92 modePlot.plot.getAxisLabels().setYLabel('ControllerType');
93 modePlot.plot.setDefaultYRange([-0.1, 3.1]);
94
95 const controllerType = modePlot.addMessageLine(goal, ['controller_type']);
96 controllerType.setDrawLine(false);
97
98 // Drivetrain Output Voltage
99 const outputPlot =
100 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
101 currentTop += height;
102 outputPlot.plot.getAxisLabels().setTitle('Drivetrain Output');
103 outputPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
104 outputPlot.plot.getAxisLabels().setYLabel('Voltage (V)');
105
106 const leftVoltage = outputPlot.addMessageLine(output, ['left_voltage']);
107 leftVoltage.setColor(kRed);
108 const rightVoltage = outputPlot.addMessageLine(output, ['right_voltage']);
109 rightVoltage.setColor(kGreen);
110
111 // Voltage Errors
112 const voltageErrors =
113 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
114 currentTop += height;
115 voltageErrors.plot.getAxisLabels().setTitle('Voltage Errors');
116 voltageErrors.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
117 voltageErrors.plot.getAxisLabels().setYLabel('Voltage (V)');
118
119 const leftVoltageError =
120 voltageErrors.addMessageLine(status, ['left_voltage_error']);
121 leftVoltageError.setColor(kRed);
122 const rightVoltageError =
123 voltageErrors.addMessageLine(status, ['right_voltage_error']);
124 rightVoltageError.setColor(kGreen);
125
126 const ekfLeftVoltageError =
127 voltageErrors.addMessageLine(status, ['localizer', 'left_voltage_error']);
128 ekfLeftVoltageError.setColor(kPink);
129 const ekfRightVoltageError = voltageErrors.addMessageLine(
130 status, ['localizer', 'right_voltage_error']);
131 ekfRightVoltageError.setColor(kCyan);
132
133 // Sundry components of the output voltages
134 const otherVoltages =
135 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
136 currentTop += height;
137 otherVoltages.plot.getAxisLabels().setTitle('Other Voltage Components');
138 otherVoltages.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
139 otherVoltages.plot.getAxisLabels().setYLabel('Voltage (V)');
140
141 const ffLeftVoltage = otherVoltages.addMessageLine(
142 status, ['poly_drive_logging', 'ff_left_voltage']);
143 ffLeftVoltage.setColor(kRed);
144 ffLeftVoltage.setPointSize(0);
145 const ffRightVoltage = otherVoltages.addMessageLine(
146 status, ['poly_drive_logging', 'ff_right_voltage']);
147 ffRightVoltage.setColor(kGreen);
148 ffRightVoltage.setPointSize(0);
149
150 const uncappedLeftVoltage =
151 otherVoltages.addMessageLine(status, ['uncapped_left_voltage']);
152 uncappedLeftVoltage.setColor(kRed);
153 uncappedLeftVoltage.setDrawLine(false);
154 const uncappedRightVoltage =
155 otherVoltages.addMessageLine(status, ['uncapped_right_voltage']);
156 uncappedRightVoltage.setColor(kGreen);
157 uncappedRightVoltage.setDrawLine(false);
158
159 // Drivetrain Velocities
160 const velocityPlot =
161 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
162 currentTop += height;
163 velocityPlot.plot.getAxisLabels().setTitle('Velocity Plots');
164 velocityPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
165 velocityPlot.plot.getAxisLabels().setYLabel('Wheel Velocity (m/s)');
166
167 const ssLeftVelocityGoal =
168 velocityPlot.addMessageLine(status, ['profiled_left_velocity_goal']);
169 ssLeftVelocityGoal.setColor(kPink);
170 ssLeftVelocityGoal.setPointSize(0.0);
171 const ssRightVelocityGoal =
172 velocityPlot.addMessageLine(status, ['profiled_right_velocity_goal']);
173 ssRightVelocityGoal.setColor(kCyan);
174 ssRightVelocityGoal.setPointSize(0.0);
175
176 const polyLeftVelocity = velocityPlot.addMessageLine(
177 status, ['poly_drive_logging', 'goal_left_velocity']);
178 polyLeftVelocity.setColor(kPink);
179 polyLeftVelocity.setDrawLine(false);
180
181 const polyRightVelocity = velocityPlot.addMessageLine(
182 status, ['poly_drive_logging', 'goal_right_velocity']);
183 polyRightVelocity.setColor(kCyan);
184 polyRightVelocity.setDrawLine(false);
185
186 const splineLeftVelocity = velocityPlot.addMessageLine(
187 status, ['trajectory_logging', 'left_velocity']);
188 splineLeftVelocity.setColor(kRed);
189 splineLeftVelocity.setDrawLine(false);
190
191 const splineRightVelocity = velocityPlot.addMessageLine(
192 status, ['trajectory_logging', 'right_velocity']);
193 splineRightVelocity.setColor(kGreen);
194 splineRightVelocity.setDrawLine(false);
195
196 const leftVelocity =
197 velocityPlot.addMessageLine(status, ['estimated_left_velocity']);
198 leftVelocity.setColor(kRed);
199 const rightVelocity =
200 velocityPlot.addMessageLine(status, ['estimated_right_velocity']);
201 rightVelocity.setColor(kGreen);
202
203 const ekfLeftVelocity =
204 velocityPlot.addMessageLine(status, ['localizer', 'left_velocity']);
205 ekfLeftVelocity.setColor(kRed);
206 ekfLeftVelocity.setPointSize(0.0);
207 const ekfRightVelocity =
208 velocityPlot.addMessageLine(status, ['localizer', 'right_velocity']);
209 ekfRightVelocity.setColor(kGreen);
210 ekfRightVelocity.setPointSize(0.0);
211
212 // Heading
213 const yawPlot = aosPlotter.addPlot(element, [0, currentTop], [width, height]);
214 currentTop += height;
215 yawPlot.plot.getAxisLabels().setTitle('Robot Yaw');
216 yawPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
217 yawPlot.plot.getAxisLabels().setYLabel('Yaw (rad)');
218
219 const splineYaw =
220 yawPlot.addMessageLine(status, ['trajectory_logging', 'theta']);
221 splineYaw.setDrawLine(false);
222 splineYaw.setColor(kRed);
223
224 const ekfYaw = yawPlot.addMessageLine(status, ['localizer', 'theta']);
225 ekfYaw.setColor(kGreen);
226
227 const downEstimatorYaw =
228 yawPlot.addMessageLine(status, ['down_estimator', 'yaw']);
229 downEstimatorYaw.setColor(kBlue);
230
231 // Pitch/Roll
232 const orientationPlot =
233 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
234 currentTop += height;
235 orientationPlot.plot.getAxisLabels().setTitle('Orientation');
236 orientationPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
237 orientationPlot.plot.getAxisLabels().setYLabel('Angle (rad)');
238
239 const roll = orientationPlot.addMessageLine(
240 status, ['down_estimator', 'lateral_pitch']);
241 roll.setColor(kRed);
242 roll.setLabel('roll');
243 const pitch = orientationPlot.addMessageLine(
244 status, ['down_estimator', 'longitudinal_pitch']);
245 pitch.setColor(kGreen);
246 pitch.setLabel('pitch');
247
248 // Accelerometer/Gravity
249 const accelPlot =
250 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
251 currentTop += height;
252 accelPlot.plot.getAxisLabels().setTitle('Accelerometer Readings');
253 accelPlot.plot.getAxisLabels().setYLabel('Acceleration (g)');
254 accelPlot.plot.getAxisLabels().setXLabel('Monotonic Reading Time (sec)');
255
256 const expectedAccelX =
257 accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_x']);
258 expectedAccelX.setColor(kRed);
259 expectedAccelX.setPointSize(0);
260 const expectedAccelY =
261 accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_y']);
262 expectedAccelY.setColor(kGreen);
263 expectedAccelY.setPointSize(0);
264 const expectedAccelZ =
265 accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_z']);
266 expectedAccelZ.setColor(kBlue);
267 expectedAccelZ.setPointSize(0);
268
269 const gravity_magnitude =
270 accelPlot.addMessageLine(status, ['down_estimator', 'gravity_magnitude']);
271 gravity_magnitude.setColor(kWhite);
272 gravity_magnitude.setPointSize(0);
273
274 const accelX = accelPlot.addMessageLine(imu, ['accelerometer_x']);
275 accelX.setColor(kRed);
276 accelX.setDrawLine(false);
277 const accelY = accelPlot.addMessageLine(imu, ['accelerometer_y']);
278 accelY.setColor(kGreen);
279 accelY.setDrawLine(false);
280 const accelZ = accelPlot.addMessageLine(imu, ['accelerometer_z']);
281 accelZ.setColor(kBlue);
282 accelZ.setDrawLine(false);
283
284 // Absolute X Position
285 const xPositionPlot =
286 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
287 currentTop += height;
288 xPositionPlot.plot.getAxisLabels().setTitle('X Position');
289 xPositionPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
290 xPositionPlot.plot.getAxisLabels().setYLabel('X Position (m)');
291
292 const localizerX = xPositionPlot.addMessageLine(status, ['x']);
293 localizerX.setColor(kRed);
294 const splineX =
295 xPositionPlot.addMessageLine(status, ['trajectory_logging', 'x']);
296 splineX.setColor(kGreen);
297
298 // Absolute Y Position
299 const yPositionPlot =
300 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
301 currentTop += height;
302 yPositionPlot.plot.getAxisLabels().setTitle('Y Position');
303 yPositionPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
304 yPositionPlot.plot.getAxisLabels().setYLabel('Y Position (m)');
305
306 const localizerY = yPositionPlot.addMessageLine(status, ['y']);
307 localizerY.setColor(kRed);
308 const splineY =
309 yPositionPlot.addMessageLine(status, ['trajectory_logging', 'y']);
310 splineY.setColor(kGreen);
311
312 // Gyro
313 const gyroPlot =
314 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
315 currentTop += height;
316 gyroPlot.plot.getAxisLabels().setTitle('Gyro Readings');
317 gyroPlot.plot.getAxisLabels().setYLabel('Angular Velocity (rad / sec)');
318 gyroPlot.plot.getAxisLabels().setXLabel('Monotonic Reading Time (sec)');
319
320 const gyroZeroX =
321 gyroPlot.addMessageLine(status, ['zeroing', 'gyro_x_average']);
322 gyroZeroX.setColor(kRed);
323 gyroZeroX.setPointSize(0);
324 gyroZeroX.setLabel('Gyro X Zero');
325 const gyroZeroY =
326 gyroPlot.addMessageLine(status, ['zeroing', 'gyro_y_average']);
327 gyroZeroY.setColor(kGreen);
328 gyroZeroY.setPointSize(0);
329 gyroZeroY.setLabel('Gyro Y Zero');
330 const gyroZeroZ =
331 gyroPlot.addMessageLine(status, ['zeroing', 'gyro_z_average']);
332 gyroZeroZ.setColor(kBlue);
333 gyroZeroZ.setPointSize(0);
334 gyroZeroZ.setLabel('Gyro Z Zero');
335
336 const gyroX = gyroPlot.addMessageLine(imu, ['gyro_x']);
337 gyroX.setColor(kRed);
338 const gyroY = gyroPlot.addMessageLine(imu, ['gyro_y']);
339 gyroY.setColor(kGreen);
340 const gyroZ = gyroPlot.addMessageLine(imu, ['gyro_z']);
341 gyroZ.setColor(kBlue);
342
343 // IMU States
344 const imuStatePlot =
345 aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
346 currentTop += height / 2;
347 imuStatePlot.plot.getAxisLabels().setTitle('IMU State');
348 imuStatePlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
349 imuStatePlot.plot.setDefaultYRange([-0.1, 1.1]);
350
351 const zeroedLine = imuStatePlot.addMessageLine(status, ['zeroing', 'zeroed']);
352 zeroedLine.setColor(kRed);
353 zeroedLine.setDrawLine(false);
354 zeroedLine.setLabel('IMU Zeroed');
355 const faultedLine =
356 imuStatePlot.addMessageLine(status, ['zeroing', 'faulted']);
357 faultedLine.setColor(kGreen);
358 faultedLine.setPointSize(0);
359 faultedLine.setLabel('IMU Faulted');
360}