blob: f56a6bf2abe836fdfef534e57b34348db94a85c4 [file] [log] [blame]
James Kuszmaul5f5e1232020-12-22 20:58:00 -08001// This file provides an index of all standard plot configs.
2// In the future, this may be split into more pieces (e.g., to have
3// year-specific indices). For now, the pattern for creating a new plot
4// is that you provide an exported function (a la the plot*() functions imported
5// below) which, when called, will generate the plot in the provided div.
6// This file handles providing a master list of all known plots so that
7// the user can just open a single web-page and select the plot that they want
8// from a drop-down. A given plot will not be loaded until it has been selected
9// once, at which point it will stay loaded. This means that if the user wants
10// to switch between several plot configs, they don't incur any performance
11// penalty associated with swapping.
12// By default, no plot is selected, but the plot= URL parameter may be used
13// to specify a specific plot, so that people can create links to a specific
14// plot.
15// The plot*() functions are called *after* we have already received a valid
16// config from the web server, so config handlers do not need to be used.
17//
18// The exact setup of this will be in flux as we add more configs and figure out
19// what setups work best--we will likely end up with separate index files for
20// each robot year, and may even end up allowing plots to be specified solely
21// using JSON rather than requiring people to write a script just to create
22// a plot.
23import * as configuration from 'org_frc971/aos/configuration_generated';
24import * as proxy from 'org_frc971/aos/network/www/proxy';
25import {plotImu} from 'org_frc971/frc971/wpilib/imu_plotter';
James Kuszmaulc4ae11c2020-12-26 16:26:58 -080026import {plotDrivetrain} from 'org_frc971/frc971/control_loops/drivetrain/drivetrain_plotter';
James Kuszmaul73fc1352021-04-09 22:31:25 -070027import {plotSpline} from 'org_frc971/frc971/control_loops/drivetrain/spline_plotter';
James Kuszmaulac2b6b42021-03-07 22:38:06 -080028import {plotDownEstimator} from 'org_frc971/frc971/control_loops/drivetrain/down_estimator_plotter';
milind upadhyay9bd381d2021-01-23 13:44:13 -080029import {plotRobotState} from
30 'org_frc971/frc971/control_loops/drivetrain/robot_state_plotter'
Milind Upadhyayeb739bb2022-03-02 10:49:21 -080031import {plotFinisher as plot2020Finisher} from
Austin Schuh7d63eab2021-03-06 20:15:02 -080032 'org_frc971/y2020/control_loops/superstructure/finisher_plotter'
Milind Upadhyayeb739bb2022-03-02 10:49:21 -080033import {plotTurret as plot2020Turret} from
James Kuszmaul78101402021-09-11 12:42:21 -070034 'org_frc971/y2020/control_loops/superstructure/turret_plotter'
James Kuszmaulf7c8a092022-02-12 16:46:09 -080035import {plotLocalizer as plot2020Localizer} from
James Kuszmaul9c23d262021-09-25 21:50:02 -070036 'org_frc971/y2020/control_loops/drivetrain/localizer_plotter'
Milind Upadhyayeb739bb2022-03-02 10:49:21 -080037import {plotAccelerator as plot2020Accelerator} from
38 'org_frc971/y2020/control_loops/superstructure/accelerator_plotter'
39import {plotHood as plot2020Hood} from
40 'org_frc971/y2020/control_loops/superstructure/hood_plotter'
41import {plotSuperstructure as plot2021Superstructure} from
42 'org_frc971/y2021_bot3/control_loops/superstructure/superstructure_plotter';
43import {plotTurret as plot2022Turret} from
44 'org_frc971/y2022/control_loops/superstructure/turret_plotter'
Austin Schuh76f227c2022-02-23 16:34:08 -080045import {plotCatapult as plot2022Catapult} from
46 'org_frc971/y2022/control_loops/superstructure/catapult_plotter'
Milind Upadhyayeb739bb2022-03-02 10:49:21 -080047import {plotIntake as plot2022Intake} from
48 'org_frc971/y2022/control_loops/superstructure/intake_plotter'
49import {plotClimber as plot2022Climber} from
50 'org_frc971/y2022/control_loops/superstructure/climber_plotter'
James Kuszmaulf7c8a092022-02-12 16:46:09 -080051import {plotLocalizer as plot2022Localizer} from
James Kuszmaul51fa1ae2022-02-26 00:49:57 -080052 'org_frc971/y2022/localizer/localizer_plotter'
James Kuszmaul5f5e1232020-12-22 20:58:00 -080053import {plotDemo} from 'org_frc971/aos/network/www/demo_plot';
James Kuszmaul48671362020-12-24 13:54:16 -080054import {plotData} from 'org_frc971/frc971/analysis/plot_data_utils';
James Kuszmaul5f5e1232020-12-22 20:58:00 -080055
56import Connection = proxy.Connection;
57import Configuration = configuration.aos.Configuration;
58
59const rootDiv = document.createElement('div');
60document.body.appendChild(rootDiv);
61
62const helpDiv = document.createElement('div');
63rootDiv.appendChild(helpDiv);
64helpDiv.innerHTML =
James Kuszmaul461b0682020-12-22 22:20:21 -080065 'Help: click + drag to pan, double click to reset, scroll to zoom, ' +
66 'right-click + drag to zoom to rectangle, Esc to cancel. ' +
James Kuszmaul5f5e1232020-12-22 20:58:00 -080067 'Hold the x/y keys to only pan/zoom along the x/y axes.';
68
69class PlotState {
70 public readonly div: HTMLElement;
71 private initialized = false;
72 constructor(
73 parentDiv: HTMLElement,
74 private readonly initializer:
75 (conn: Connection, element: Element) => void) {
76 this.div = document.createElement('div');
77 parentDiv.appendChild(this.div);
78 this.hide();
79 }
80 initialize(conn: Connection): void {
81 if (!this.initialized) {
82 this.initializer(conn, this.div);
83 this.initialized = true;
84 }
85 }
86 hide(): void {
87 this.div.style.display = "none";
88 }
89 show(): void {
90 this.div.style.display = "block";
91 }
92}
93
94const plotSelect = document.createElement('select');
95rootDiv.appendChild(plotSelect);
96
97const plotDiv = document.createElement('div');
98plotDiv.style.top = (plotSelect.getBoundingClientRect().bottom + 10).toString();
99plotDiv.style.left = '0';
100plotDiv.style.position = 'absolute';
101rootDiv.appendChild(plotDiv);
102
103// The master list of all the plots that we provide. For a given config, it
104// is possible that not all of these plots will be usable depending on the
105// presence of certain channels.
106const plotIndex = new Map<string, PlotState>([
107 ['Demo', new PlotState(plotDiv, plotDemo)],
James Kuszmaul48671362020-12-24 13:54:16 -0800108 ['IMU', new PlotState(plotDiv, plotImu)],
James Kuszmaulc4ae11c2020-12-26 16:26:58 -0800109 ['Drivetrain', new PlotState(plotDiv, plotDrivetrain)],
James Kuszmaul73fc1352021-04-09 22:31:25 -0700110 ['Spline Debug', new PlotState(plotDiv, plotSpline)],
James Kuszmaulac2b6b42021-03-07 22:38:06 -0800111 ['Down Estimator', new PlotState(plotDiv, plotDownEstimator)],
milind upadhyay9bd381d2021-01-23 13:44:13 -0800112 ['Robot State', new PlotState(plotDiv, plotRobotState)],
Milind Upadhyayeb739bb2022-03-02 10:49:21 -0800113 ['2020 Finisher', new PlotState(plotDiv, plot2020Finisher)],
114 ['2020 Accelerator', new PlotState(plotDiv, plot2020Accelerator)],
115 ['2020 Hood', new PlotState(plotDiv, plot2020Hood)],
116 ['2020 Turret', new PlotState(plotDiv, plot2020Turret)],
James Kuszmaulf7c8a092022-02-12 16:46:09 -0800117 ['2020 Localizer', new PlotState(plotDiv, plot2020Localizer)],
Milind Upadhyayeb739bb2022-03-02 10:49:21 -0800118 ['2022 Localizer', new PlotState(plotDiv, plot2022Localizer)],
Austin Schuh76f227c2022-02-23 16:34:08 -0800119 ['2022 Catapult', new PlotState(plotDiv, plot2022Catapult)],
Milind Upadhyayeb739bb2022-03-02 10:49:21 -0800120 ['2022 Intake', new PlotState(plotDiv, plot2022Intake)],
121 ['2022 Climber', new PlotState(plotDiv, plot2022Climber)],
122 ['2022 Turret', new PlotState(plotDiv, plot2022Turret)],
James Kuszmaul48671362020-12-24 13:54:16 -0800123 ['C++ Plotter', new PlotState(plotDiv, plotData)],
Milind Upadhyayeb739bb2022-03-02 10:49:21 -0800124 ['Y2021 3rd Robot Superstructure', new PlotState(plotDiv, plot2021Superstructure)],
James Kuszmaul5f5e1232020-12-22 20:58:00 -0800125]);
126
127const invalidSelectValue = 'null';
128function getDefaultPlot(): string {
129 const urlParams = (new URL(document.URL)).searchParams;
130 const urlParamKey = 'plot';
131 if (!urlParams.has(urlParamKey)) {
132 return invalidSelectValue;
133 }
134 const desiredPlot = urlParams.get(urlParamKey);
135 if (!plotIndex.has(desiredPlot)) {
136 return invalidSelectValue;
137 }
138 return desiredPlot;
139}
140
141const conn = new Connection();
142
James Kuszmaulb8989f72021-03-07 20:00:02 -0800143let reloadOnChange = false;
144
James Kuszmaul5f5e1232020-12-22 20:58:00 -0800145conn.connect();
146
147conn.addConfigHandler((config: Configuration) => {
148 plotSelect.add(new Option("Select Plot", invalidSelectValue));
149 for (const name of plotIndex.keys()) {
150 plotSelect.add(new Option(name, name));
151 }
152 plotSelect.addEventListener('input', () => {
153 for (const plot of plotIndex.values()) {
154 plot.hide();
155 }
156 if (plotSelect.value == invalidSelectValue) {
157 return;
158 }
159 plotIndex.get(plotSelect.value).initialize(conn);
160 plotIndex.get(plotSelect.value).show();
James Kuszmaulc4ae11c2020-12-26 16:26:58 -0800161 // Set the URL so that if you reload you get back to this plot.
162 window.history.replaceState(
163 null, null, '?plot=' + encodeURIComponent(plotSelect.value));
James Kuszmaulb8989f72021-03-07 20:00:02 -0800164 if (reloadOnChange) {
165 window.location.reload();
166 }
167 reloadOnChange = true;
James Kuszmaul5f5e1232020-12-22 20:58:00 -0800168 });
169 plotSelect.value = getDefaultPlot();
170 // Force the event to occur once at the start.
171 plotSelect.dispatchEvent(new Event('input'));
James Kuszmaulf7c8a092022-02-12 16:46:09 -0800172});