James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 1 | // Provides a plot for debugging robot state-related issues. |
| 2 | import {AosPlotter} from 'org_frc971/aos/network/www/aos_plotter'; |
| 3 | import * as proxy from 'org_frc971/aos/network/www/proxy'; |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 4 | import * as configuration from 'org_frc971/aos/configuration_generated'; |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 5 | import {BLUE, BROWN, CYAN, GREEN, PINK, RED, WHITE} from 'org_frc971/aos/network/www/colors'; |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 6 | import {MessageHandler, TimestampedMessage} from 'org_frc971/aos/network/www/aos_plotter'; |
| 7 | import {Point} from 'org_frc971/aos/network/www/plotter'; |
| 8 | import {Table} from 'org_frc971/aos/network/www/reflection'; |
| 9 | import {ByteBuffer} from 'org_frc971/external/com_github_google_flatbuffers/ts/byte-buffer'; |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 10 | |
| 11 | import Connection = proxy.Connection; |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 12 | import Schema = configuration.reflection.Schema; |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 13 | |
| 14 | const TIME = AosPlotter.TIME; |
| 15 | const DEFAULT_WIDTH = AosPlotter.DEFAULT_WIDTH; |
| 16 | const DEFAULT_HEIGHT = AosPlotter.DEFAULT_HEIGHT; |
| 17 | |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 18 | class DerivativeMessageHandler extends MessageHandler { |
| 19 | // Calculated magnitude of the measured acceleration from the IMU. |
| 20 | private acceleration_magnitudes: Point[] = []; |
| 21 | constructor(private readonly schema: Schema) { |
| 22 | super(schema); |
| 23 | } |
| 24 | private readScalar(table: Table, fieldName: string): number { |
| 25 | return this.parser.readScalar(table, fieldName); |
| 26 | } |
| 27 | |
| 28 | // Computes a numerical derivative for a given input. |
| 29 | private derivative(input: Point[]): Point[] { |
| 30 | const num_measurements = input.length; |
| 31 | const results = []; |
| 32 | for (let ii = 0; ii < num_measurements - 1; ++ii) { |
| 33 | const x0 = input[ii].x; |
| 34 | const x1 = input[ii + 1].x; |
| 35 | const y0 = input[ii].y; |
| 36 | const y1 = input[ii + 1].y; |
| 37 | results.push(new Point((x0 + x1) / 2.0, (y1 - y0) / (x1 - x0))); |
| 38 | } |
| 39 | return results; |
| 40 | } |
| 41 | |
| 42 | getField(field: string[]): Point[] { |
| 43 | // Any requested input that ends with "_derivative" will get a derivative |
| 44 | // calculated for the provided field. |
| 45 | const derivative_suffix = "_derivative"; |
| 46 | const num_fields = field.length; |
| 47 | const end_field = field[num_fields - 1]; |
| 48 | if (end_field.endsWith(derivative_suffix)) { |
| 49 | const field_copy = []; |
| 50 | for (let ii = 0; ii < num_fields - 1; ++ii) { |
| 51 | field_copy.push(field[ii]); |
| 52 | } |
| 53 | field_copy.push(end_field.slice(0, end_field.length - derivative_suffix.length)); |
| 54 | return this.derivative(this.getField(field_copy)); |
| 55 | } else { |
| 56 | return super.getField(field); |
| 57 | } |
| 58 | } |
| 59 | } |
| 60 | |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 61 | export function plotTurret(conn: Connection, element: Element) : void { |
| 62 | const aosPlotter = new AosPlotter(conn); |
| 63 | const goal = aosPlotter.addMessageSource('/superstructure', 'y2020.control_loops.superstructure.Goal'); |
| 64 | const output = aosPlotter.addMessageSource('/superstructure', 'y2020.control_loops.superstructure.Output'); |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 65 | const status = aosPlotter.addRawMessageSource( |
| 66 | '/superstructure', 'y2020.control_loops.superstructure.Status', |
| 67 | new DerivativeMessageHandler(conn.getSchema('y2020.control_loops.superstructure.Status')) |
| 68 | ); |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 69 | const pdpValues = |
| 70 | aosPlotter.addMessageSource('/roborio/aos', 'frc971.PDPValues'); |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 71 | const localizerDebug = |
| 72 | aosPlotter.addMessageSource('/drivetrain', 'y2020.control_loops.drivetrain.LocalizerDebug'); |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 73 | |
| 74 | var currentTop = 0; |
| 75 | |
| 76 | const turretPosPlot = aosPlotter.addPlot( |
| 77 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 78 | currentTop += DEFAULT_HEIGHT; |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 79 | turretPosPlot.plot.getAxisLabels().setTitle('Turret Position'); |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 80 | turretPosPlot.plot.getAxisLabels().setXLabel(TIME); |
| 81 | turretPosPlot.plot.getAxisLabels().setYLabel('rad'); |
| 82 | |
| 83 | turretPosPlot.addMessageLine(status, ['aimer', 'turret_position']) |
| 84 | .setColor(RED) |
| 85 | .setPointSize(0.0); |
| 86 | turretPosPlot.addMessageLine(status, ['turret', 'position']) |
| 87 | .setColor(GREEN) |
| 88 | .setPointSize(0.0); |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 89 | turretPosPlot.addMessageLine(localizerDebug, ['matches[]', 'implied_turret_goal']) |
| 90 | .setColor(GREEN) |
| 91 | .setDrawLine(false); |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 92 | turretPosPlot.addMessageLine(status, ['turret', 'unprofiled_goal_position']) |
| 93 | .setColor(BLUE) |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 94 | .setDrawLine(false); |
| 95 | |
| 96 | const turretVelPlot = aosPlotter.addPlot( |
| 97 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 98 | currentTop += DEFAULT_HEIGHT; |
| 99 | turretVelPlot.plot.getAxisLabels().setTitle('Turret Velocity'); |
| 100 | turretVelPlot.plot.getAxisLabels().setXLabel(TIME); |
| 101 | turretVelPlot.plot.getAxisLabels().setYLabel('rad / sec'); |
| 102 | |
| 103 | turretVelPlot.addMessageLine(status, ['aimer', 'turret_velocity']) |
| 104 | .setColor(RED) |
| 105 | .setPointSize(0.0); |
| 106 | turretVelPlot.addMessageLine(status, ['turret', 'velocity']) |
| 107 | .setColor(GREEN) |
| 108 | .setPointSize(0.0); |
| 109 | turretVelPlot.addMessageLine(status, ['turret', 'unprofiled_goal_velocity']) |
| 110 | .setColor(BLUE) |
| 111 | .setDrawLine(false); |
| 112 | |
| 113 | const turretAccelPlot = aosPlotter.addPlot( |
| 114 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 115 | currentTop += DEFAULT_HEIGHT; |
| 116 | turretAccelPlot.plot.getAxisLabels().setTitle('Turret Acceleration'); |
| 117 | turretAccelPlot.plot.getAxisLabels().setXLabel(TIME); |
| 118 | turretAccelPlot.plot.getAxisLabels().setYLabel('rad / sec / sec'); |
| 119 | |
| 120 | turretAccelPlot.addMessageLine(status, ['aimer', 'turret_velocity_derivative']) |
| 121 | .setColor(RED) |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 122 | .setPointSize(0.0); |
| 123 | |
| 124 | const turretVoltagePlot = aosPlotter.addPlot( |
| 125 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 126 | currentTop += DEFAULT_HEIGHT; |
| 127 | turretVoltagePlot.plot.getAxisLabels().setTitle('Turret Voltage'); |
| 128 | turretVoltagePlot.plot.getAxisLabels().setXLabel(TIME); |
| 129 | turretVoltagePlot.plot.getAxisLabels().setYLabel('V'); |
| 130 | |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 131 | turretVoltagePlot.addMessageLine(status, ['turret', 'voltage_error']) |
| 132 | .setColor(GREEN) |
| 133 | .setPointSize(0.0); |
| 134 | turretVoltagePlot.addMessageLine(status, ['turret', 'position_power']) |
| 135 | .setColor(BLUE) |
| 136 | .setPointSize(0.0); |
| 137 | turretVoltagePlot.addMessageLine(status, ['turret', 'velocity_power']) |
| 138 | .setColor(CYAN) |
| 139 | .setPointSize(0.0); |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 140 | turretVoltagePlot.addMessageLine(output, ['turret_voltage']) |
| 141 | .setColor(RED) |
| 142 | .setPointSize(0.0); |
| 143 | |
| 144 | const currentPlot = aosPlotter.addPlot( |
| 145 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 146 | currentTop += DEFAULT_HEIGHT; |
| 147 | currentPlot.plot.getAxisLabels().setTitle('Current'); |
| 148 | currentPlot.plot.getAxisLabels().setXLabel(TIME); |
| 149 | currentPlot.plot.getAxisLabels().setYLabel('Amps'); |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 150 | currentPlot.plot.setDefaultYRange([0.0, 40.0]); |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 151 | |
| 152 | currentPlot.addMessageLine(pdpValues, ['currents[6]']) |
| 153 | .setColor(GREEN) |
| 154 | .setPointSize(0.0); |
| 155 | |
| 156 | |
| 157 | const targetDistancePlot = aosPlotter.addPlot( |
| 158 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 159 | currentTop += DEFAULT_HEIGHT; |
| 160 | targetDistancePlot.plot.getAxisLabels().setTitle('Target distance'); |
| 161 | targetDistancePlot.plot.getAxisLabels().setXLabel(TIME); |
| 162 | targetDistancePlot.plot.getAxisLabels().setYLabel('m'); |
| 163 | |
| 164 | targetDistancePlot.addMessageLine(status, ['aimer', 'target_distance']) |
| 165 | .setColor(RED) |
| 166 | .setPointSize(0.0); |
| 167 | |
| 168 | const targetChoicePlot = aosPlotter.addPlot( |
| 169 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 170 | currentTop += DEFAULT_HEIGHT; |
| 171 | targetChoicePlot.plot.getAxisLabels().setTitle('Target choice'); |
| 172 | targetChoicePlot.plot.getAxisLabels().setXLabel(TIME); |
| 173 | targetChoicePlot.plot.getAxisLabels().setYLabel('[bool]'); |
| 174 | targetChoicePlot.plot.setDefaultYRange([-0.05, 1.05]); |
| 175 | |
| 176 | targetChoicePlot.addMessageLine(status, ['aimer', 'aiming_for_inner_port']) |
| 177 | .setColor(RED) |
| 178 | .setPointSize(0.0); |
James Kuszmaul | da52ce6 | 2021-09-25 21:51:42 -0700 | [diff] [blame] | 179 | |
| 180 | const imageAcceptedPlot = aosPlotter.addPlot( |
| 181 | element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]); |
| 182 | currentTop += DEFAULT_HEIGHT; |
| 183 | imageAcceptedPlot.plot.getAxisLabels().setTitle('Image Acceptance'); |
| 184 | imageAcceptedPlot.plot.getAxisLabels().setXLabel(TIME); |
| 185 | imageAcceptedPlot.plot.getAxisLabels().setYLabel('[bool]'); |
| 186 | imageAcceptedPlot.plot.setDefaultYRange([-0.05, 1.05]); |
| 187 | |
| 188 | imageAcceptedPlot.addMessageLine(localizerDebug, ['matches[]', 'accepted']) |
| 189 | .setColor(RED) |
| 190 | .setDrawLine(false); |
James Kuszmaul | 7810140 | 2021-09-11 12:42:21 -0700 | [diff] [blame] | 191 | } |