blob: dd42d206da77a202e3ba1203407b796c85260f90 [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
milind upadhyayb81e6a42021-01-08 19:48:30 -080098 // Drivetrain estimated relative position
99 const positionPlot = aosPlotter.addPlot(element, [0, currentTop],
100 [width, height]);
101 currentTop += height;
102 positionPlot.plot.getAxisLabels().setTitle("Estimated Relative Position " +
103 "of the Drivetrain");
104 positionPlot.plot.getAxisLabels().setXLabel("Monotonic Time (sec)");
105 positionPlot.plot.getAxisLabels().setYLabel("Relative Position (m)");
106 const leftPosition =
107 positionPlot.addMessageLine(status, ["estimated_left_position"]);
108 leftPosition.setColor(kRed);
109 const rightPosition =
110 positionPlot.addMessageLine(status, ["estimated_right_position"]);
111 rightPosition.setColor(kGreen);
112 const leftPositionGoal =
113 positionPlot.addMessageLine(status, ["profiled_left_position_goal"]);
114 leftPositionGoal.setColor(kBlue);
115 const rightPositionGoal =
116 positionPlot.addMessageLine(status, ["profiled_right_position_goal"]);
117 rightPositionGoal.setColor(kPink);
118
James Kuszmaulc4ae11c2020-12-26 16:26:58 -0800119 // Drivetrain Output Voltage
120 const outputPlot =
121 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
122 currentTop += height;
123 outputPlot.plot.getAxisLabels().setTitle('Drivetrain Output');
124 outputPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
125 outputPlot.plot.getAxisLabels().setYLabel('Voltage (V)');
126
127 const leftVoltage = outputPlot.addMessageLine(output, ['left_voltage']);
128 leftVoltage.setColor(kRed);
129 const rightVoltage = outputPlot.addMessageLine(output, ['right_voltage']);
130 rightVoltage.setColor(kGreen);
131
132 // Voltage Errors
133 const voltageErrors =
134 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
135 currentTop += height;
136 voltageErrors.plot.getAxisLabels().setTitle('Voltage Errors');
137 voltageErrors.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
138 voltageErrors.plot.getAxisLabels().setYLabel('Voltage (V)');
139
140 const leftVoltageError =
141 voltageErrors.addMessageLine(status, ['left_voltage_error']);
142 leftVoltageError.setColor(kRed);
143 const rightVoltageError =
144 voltageErrors.addMessageLine(status, ['right_voltage_error']);
145 rightVoltageError.setColor(kGreen);
146
147 const ekfLeftVoltageError =
148 voltageErrors.addMessageLine(status, ['localizer', 'left_voltage_error']);
149 ekfLeftVoltageError.setColor(kPink);
150 const ekfRightVoltageError = voltageErrors.addMessageLine(
151 status, ['localizer', 'right_voltage_error']);
152 ekfRightVoltageError.setColor(kCyan);
153
154 // Sundry components of the output voltages
155 const otherVoltages =
156 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
157 currentTop += height;
158 otherVoltages.plot.getAxisLabels().setTitle('Other Voltage Components');
159 otherVoltages.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
160 otherVoltages.plot.getAxisLabels().setYLabel('Voltage (V)');
161
162 const ffLeftVoltage = otherVoltages.addMessageLine(
163 status, ['poly_drive_logging', 'ff_left_voltage']);
164 ffLeftVoltage.setColor(kRed);
165 ffLeftVoltage.setPointSize(0);
166 const ffRightVoltage = otherVoltages.addMessageLine(
167 status, ['poly_drive_logging', 'ff_right_voltage']);
168 ffRightVoltage.setColor(kGreen);
169 ffRightVoltage.setPointSize(0);
170
171 const uncappedLeftVoltage =
172 otherVoltages.addMessageLine(status, ['uncapped_left_voltage']);
173 uncappedLeftVoltage.setColor(kRed);
174 uncappedLeftVoltage.setDrawLine(false);
175 const uncappedRightVoltage =
176 otherVoltages.addMessageLine(status, ['uncapped_right_voltage']);
177 uncappedRightVoltage.setColor(kGreen);
178 uncappedRightVoltage.setDrawLine(false);
179
180 // Drivetrain Velocities
181 const velocityPlot =
182 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
183 currentTop += height;
184 velocityPlot.plot.getAxisLabels().setTitle('Velocity Plots');
185 velocityPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
186 velocityPlot.plot.getAxisLabels().setYLabel('Wheel Velocity (m/s)');
187
188 const ssLeftVelocityGoal =
189 velocityPlot.addMessageLine(status, ['profiled_left_velocity_goal']);
190 ssLeftVelocityGoal.setColor(kPink);
191 ssLeftVelocityGoal.setPointSize(0.0);
192 const ssRightVelocityGoal =
193 velocityPlot.addMessageLine(status, ['profiled_right_velocity_goal']);
194 ssRightVelocityGoal.setColor(kCyan);
195 ssRightVelocityGoal.setPointSize(0.0);
196
197 const polyLeftVelocity = velocityPlot.addMessageLine(
198 status, ['poly_drive_logging', 'goal_left_velocity']);
199 polyLeftVelocity.setColor(kPink);
200 polyLeftVelocity.setDrawLine(false);
201
202 const polyRightVelocity = velocityPlot.addMessageLine(
203 status, ['poly_drive_logging', 'goal_right_velocity']);
204 polyRightVelocity.setColor(kCyan);
205 polyRightVelocity.setDrawLine(false);
206
207 const splineLeftVelocity = velocityPlot.addMessageLine(
208 status, ['trajectory_logging', 'left_velocity']);
209 splineLeftVelocity.setColor(kRed);
210 splineLeftVelocity.setDrawLine(false);
211
212 const splineRightVelocity = velocityPlot.addMessageLine(
213 status, ['trajectory_logging', 'right_velocity']);
214 splineRightVelocity.setColor(kGreen);
215 splineRightVelocity.setDrawLine(false);
216
217 const leftVelocity =
218 velocityPlot.addMessageLine(status, ['estimated_left_velocity']);
219 leftVelocity.setColor(kRed);
220 const rightVelocity =
221 velocityPlot.addMessageLine(status, ['estimated_right_velocity']);
222 rightVelocity.setColor(kGreen);
223
224 const ekfLeftVelocity =
225 velocityPlot.addMessageLine(status, ['localizer', 'left_velocity']);
226 ekfLeftVelocity.setColor(kRed);
227 ekfLeftVelocity.setPointSize(0.0);
228 const ekfRightVelocity =
229 velocityPlot.addMessageLine(status, ['localizer', 'right_velocity']);
230 ekfRightVelocity.setColor(kGreen);
231 ekfRightVelocity.setPointSize(0.0);
232
233 // Heading
234 const yawPlot = aosPlotter.addPlot(element, [0, currentTop], [width, height]);
235 currentTop += height;
236 yawPlot.plot.getAxisLabels().setTitle('Robot Yaw');
237 yawPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
238 yawPlot.plot.getAxisLabels().setYLabel('Yaw (rad)');
239
240 const splineYaw =
241 yawPlot.addMessageLine(status, ['trajectory_logging', 'theta']);
242 splineYaw.setDrawLine(false);
243 splineYaw.setColor(kRed);
244
245 const ekfYaw = yawPlot.addMessageLine(status, ['localizer', 'theta']);
246 ekfYaw.setColor(kGreen);
247
248 const downEstimatorYaw =
249 yawPlot.addMessageLine(status, ['down_estimator', 'yaw']);
250 downEstimatorYaw.setColor(kBlue);
251
252 // Pitch/Roll
253 const orientationPlot =
254 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
255 currentTop += height;
256 orientationPlot.plot.getAxisLabels().setTitle('Orientation');
257 orientationPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
258 orientationPlot.plot.getAxisLabels().setYLabel('Angle (rad)');
259
260 const roll = orientationPlot.addMessageLine(
261 status, ['down_estimator', 'lateral_pitch']);
262 roll.setColor(kRed);
263 roll.setLabel('roll');
264 const pitch = orientationPlot.addMessageLine(
265 status, ['down_estimator', 'longitudinal_pitch']);
266 pitch.setColor(kGreen);
267 pitch.setLabel('pitch');
268
269 // Accelerometer/Gravity
270 const accelPlot =
271 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
272 currentTop += height;
273 accelPlot.plot.getAxisLabels().setTitle('Accelerometer Readings');
274 accelPlot.plot.getAxisLabels().setYLabel('Acceleration (g)');
275 accelPlot.plot.getAxisLabels().setXLabel('Monotonic Reading Time (sec)');
276
277 const expectedAccelX =
278 accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_x']);
279 expectedAccelX.setColor(kRed);
280 expectedAccelX.setPointSize(0);
281 const expectedAccelY =
282 accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_y']);
283 expectedAccelY.setColor(kGreen);
284 expectedAccelY.setPointSize(0);
285 const expectedAccelZ =
286 accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_z']);
287 expectedAccelZ.setColor(kBlue);
288 expectedAccelZ.setPointSize(0);
289
290 const gravity_magnitude =
291 accelPlot.addMessageLine(status, ['down_estimator', 'gravity_magnitude']);
292 gravity_magnitude.setColor(kWhite);
293 gravity_magnitude.setPointSize(0);
294
295 const accelX = accelPlot.addMessageLine(imu, ['accelerometer_x']);
296 accelX.setColor(kRed);
297 accelX.setDrawLine(false);
298 const accelY = accelPlot.addMessageLine(imu, ['accelerometer_y']);
299 accelY.setColor(kGreen);
300 accelY.setDrawLine(false);
301 const accelZ = accelPlot.addMessageLine(imu, ['accelerometer_z']);
302 accelZ.setColor(kBlue);
303 accelZ.setDrawLine(false);
304
305 // Absolute X Position
306 const xPositionPlot =
307 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
308 currentTop += height;
309 xPositionPlot.plot.getAxisLabels().setTitle('X Position');
310 xPositionPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
311 xPositionPlot.plot.getAxisLabels().setYLabel('X Position (m)');
312
313 const localizerX = xPositionPlot.addMessageLine(status, ['x']);
314 localizerX.setColor(kRed);
315 const splineX =
316 xPositionPlot.addMessageLine(status, ['trajectory_logging', 'x']);
317 splineX.setColor(kGreen);
318
319 // Absolute Y Position
320 const yPositionPlot =
321 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
322 currentTop += height;
323 yPositionPlot.plot.getAxisLabels().setTitle('Y Position');
324 yPositionPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
325 yPositionPlot.plot.getAxisLabels().setYLabel('Y Position (m)');
326
327 const localizerY = yPositionPlot.addMessageLine(status, ['y']);
328 localizerY.setColor(kRed);
329 const splineY =
330 yPositionPlot.addMessageLine(status, ['trajectory_logging', 'y']);
331 splineY.setColor(kGreen);
332
333 // Gyro
334 const gyroPlot =
335 aosPlotter.addPlot(element, [0, currentTop], [width, height]);
336 currentTop += height;
337 gyroPlot.plot.getAxisLabels().setTitle('Gyro Readings');
338 gyroPlot.plot.getAxisLabels().setYLabel('Angular Velocity (rad / sec)');
339 gyroPlot.plot.getAxisLabels().setXLabel('Monotonic Reading Time (sec)');
340
341 const gyroZeroX =
342 gyroPlot.addMessageLine(status, ['zeroing', 'gyro_x_average']);
343 gyroZeroX.setColor(kRed);
344 gyroZeroX.setPointSize(0);
345 gyroZeroX.setLabel('Gyro X Zero');
346 const gyroZeroY =
347 gyroPlot.addMessageLine(status, ['zeroing', 'gyro_y_average']);
348 gyroZeroY.setColor(kGreen);
349 gyroZeroY.setPointSize(0);
350 gyroZeroY.setLabel('Gyro Y Zero');
351 const gyroZeroZ =
352 gyroPlot.addMessageLine(status, ['zeroing', 'gyro_z_average']);
353 gyroZeroZ.setColor(kBlue);
354 gyroZeroZ.setPointSize(0);
355 gyroZeroZ.setLabel('Gyro Z Zero');
356
357 const gyroX = gyroPlot.addMessageLine(imu, ['gyro_x']);
358 gyroX.setColor(kRed);
359 const gyroY = gyroPlot.addMessageLine(imu, ['gyro_y']);
360 gyroY.setColor(kGreen);
361 const gyroZ = gyroPlot.addMessageLine(imu, ['gyro_z']);
362 gyroZ.setColor(kBlue);
363
364 // IMU States
365 const imuStatePlot =
366 aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
367 currentTop += height / 2;
368 imuStatePlot.plot.getAxisLabels().setTitle('IMU State');
369 imuStatePlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
370 imuStatePlot.plot.setDefaultYRange([-0.1, 1.1]);
371
372 const zeroedLine = imuStatePlot.addMessageLine(status, ['zeroing', 'zeroed']);
373 zeroedLine.setColor(kRed);
374 zeroedLine.setDrawLine(false);
375 zeroedLine.setLabel('IMU Zeroed');
376 const faultedLine =
377 imuStatePlot.addMessageLine(status, ['zeroing', 'faulted']);
378 faultedLine.setColor(kGreen);
379 faultedLine.setPointSize(0);
380 faultedLine.setLabel('IMU Faulted');
381}