Add Position Encoder and Reader PID Plots
The position encoder plot is useful for debugging drivetrain issues
and the reader pid plot tells us if wpilib interface gets reset.
I created a new file for all robot state plots because there is a
maximum number of plots in one plotting function and the limit
was exceeded.
Change-Id: I489a1a786217ace7ded1a05ce6104205566ba70f
diff --git a/aos/network/www/aos_plotter.ts b/aos/network/www/aos_plotter.ts
index 33a3de1..ada69a9 100644
--- a/aos/network/www/aos_plotter.ts
+++ b/aos/network/www/aos_plotter.ts
@@ -131,6 +131,21 @@
}
export class AosPlotter {
+
+ public static readonly TIME: string = "Monotonic Time (sec)";
+
+ public static readonly DEFAULT_WIDTH: number = 900;
+ public static readonly DEFAULT_HEIGHT: number = 400;
+
+ public static readonly RED: number[] = [1, 0, 0];
+ public static readonly GREEN: number[] = [0, 1, 0];
+ public static readonly BLUE: number[] = [0, 0, 1];
+ public static readonly BROWN: number[] = [0.6, 0.3, 0];
+ public static readonly PINK: number[] = [1, 0.3, 0.6];
+ public static readonly CYAN: number[] = [0.3, 1, 1];
+ public static readonly WHITE: number[] = [1, 1, 1];
+
+
private plots: AosPlot[] = [];
private messages = new Set<MessageHandler>();
constructor(private readonly connection: Connection) {
diff --git a/frc971/analysis/BUILD b/frc971/analysis/BUILD
index f378b68..45e947b 100644
--- a/frc971/analysis/BUILD
+++ b/frc971/analysis/BUILD
@@ -96,6 +96,7 @@
"//aos/network/www:demo_plot",
"//aos/network/www:proxy",
"//frc971/control_loops/drivetrain:drivetrain_plotter",
+ "//frc971/control_loops/drivetrain:robot_state_plotter",
"//frc971/wpilib:imu_plotter",
],
)
diff --git a/frc971/analysis/plot_index.ts b/frc971/analysis/plot_index.ts
index 0610f6c..780f944 100644
--- a/frc971/analysis/plot_index.ts
+++ b/frc971/analysis/plot_index.ts
@@ -24,6 +24,8 @@
import * as proxy from 'org_frc971/aos/network/www/proxy';
import {plotImu} from 'org_frc971/frc971/wpilib/imu_plotter';
import {plotDrivetrain} from 'org_frc971/frc971/control_loops/drivetrain/drivetrain_plotter';
+import {plotRobotState} from
+ 'org_frc971/frc971/control_loops/drivetrain/robot_state_plotter'
import {plotDemo} from 'org_frc971/aos/network/www/demo_plot';
import {plotData} from 'org_frc971/frc971/analysis/plot_data_utils';
@@ -81,6 +83,7 @@
['Demo', new PlotState(plotDiv, plotDemo)],
['IMU', new PlotState(plotDiv, plotImu)],
['Drivetrain', new PlotState(plotDiv, plotDrivetrain)],
+ ['Robot State', new PlotState(plotDiv, plotRobotState)],
['C++ Plotter', new PlotState(plotDiv, plotData)],
]);
diff --git a/frc971/control_loops/drivetrain/BUILD b/frc971/control_loops/drivetrain/BUILD
index d42b97c..1aeec18 100644
--- a/frc971/control_loops/drivetrain/BUILD
+++ b/frc971/control_loops/drivetrain/BUILD
@@ -727,3 +727,13 @@
"//frc971/wpilib:imu_plot_utils",
],
)
+
+ts_library(
+ name = "robot_state_plotter",
+ srcs = ["robot_state_plotter.ts"],
+ target_compatible_with = ["@platforms//os:linux"],
+ deps = [
+ "//aos/network/www:aos_plotter",
+ "//aos/network/www:proxy",
+ ],
+)
diff --git a/frc971/control_loops/drivetrain/drivetrain_plotter.ts b/frc971/control_loops/drivetrain/drivetrain_plotter.ts
index dd42d20..f1ddd75 100644
--- a/frc971/control_loops/drivetrain/drivetrain_plotter.ts
+++ b/frc971/control_loops/drivetrain/drivetrain_plotter.ts
@@ -5,22 +5,23 @@
import Connection = proxy.Connection;
-const kRed = [1, 0, 0];
-const kGreen = [0, 1, 0];
-const kBlue = [0, 0, 1];
-const kBrown = [0.6, 0.3, 0];
-const kPink = [1, 0.3, 1];
-const kCyan = [0.3, 1, 1];
-const kWhite = [1, 1, 1];
+const TIME = AosPlotter.TIME;
+const DEFAULT_WIDTH = AosPlotter.DEFAULT_WIDTH;
+const DEFAULT_HEIGHT = AosPlotter.DEFAULT_HEIGHT;
+const RED = AosPlotter.RED;
+const GREEN = AosPlotter.GREEN;
+const BLUE = AosPlotter.BLUE;
+const BROWN = AosPlotter.BROWN;
+const PINK = AosPlotter.PINK;
+const CYAN = AosPlotter.CYAN;
+const WHITE = AosPlotter.WHITE;
export function plotDrivetrain(conn: Connection, element: Element): void {
- const width = 900;
- const height = 400;
const aosPlotter = new AosPlotter(conn);
- const joystickState = aosPlotter.addMessageSource('/aos', 'aos.JoystickState');
- const robotState = aosPlotter.addMessageSource('/aos', 'aos.RobotState');
const goal = aosPlotter.addMessageSource('/drivetrain', 'frc971.control_loops.drivetrain.Goal');
+ const position = aosPlotter.addMessageSource("/drivetrain",
+ "frc971.control_loops.drivetrain.Position");
const status = aosPlotter.addMessageSource(
'/drivetrain', 'frc971.control_loops.drivetrain.Status');
const output = aosPlotter.addMessageSource(
@@ -31,351 +32,322 @@
let currentTop = 0;
- // Robot Enabled/Disabled and Mode
- const robotStatePlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
- currentTop += height / 2;
- robotStatePlot.plot.getAxisLabels().setTitle('Robot State');
- robotStatePlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
- robotStatePlot.plot.getAxisLabels().setYLabel('bool');
- robotStatePlot.plot.setDefaultYRange([-0.1, 1.1]);
-
- const testMode = robotStatePlot.addMessageLine(joystickState, ['test_mode']);
- testMode.setColor(kBlue);
- testMode.setPointSize(0.0);
- const autoMode = robotStatePlot.addMessageLine(joystickState, ['autonomous']);
- autoMode.setColor(kRed);
- autoMode.setPointSize(0.0);
-
- const brownOut = robotStatePlot.addMessageLine(robotState, ['browned_out']);
- brownOut.setColor(kBrown);
- brownOut.setDrawLine(false);
- const enabled = robotStatePlot.addMessageLine(joystickState, ['enabled']);
- enabled.setColor(kGreen);
- enabled.setDrawLine(false);
-
- // Battery Voltage
- const batteryPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
- currentTop += height / 2;
- batteryPlot.plot.getAxisLabels().setTitle('Battery Voltage');
- batteryPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
- batteryPlot.plot.getAxisLabels().setYLabel('Voltage (V)');
-
- batteryPlot.addMessageLine(robotState, ['voltage_battery']);
-
// Polydrivetrain (teleop control) plots
const teleopPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
- currentTop += height / 2;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ currentTop += DEFAULT_HEIGHT / 2;
teleopPlot.plot.getAxisLabels().setTitle('Drivetrain Teleop Goals');
- teleopPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ teleopPlot.plot.getAxisLabels().setXLabel(TIME);
teleopPlot.plot.getAxisLabels().setYLabel('bool, throttle/wheel values');
teleopPlot.plot.setDefaultYRange([-1.1, 1.1]);
const quickTurn = teleopPlot.addMessageLine(goal, ['quickturn']);
- quickTurn.setColor(kRed);
+ quickTurn.setColor(RED);
const throttle = teleopPlot.addMessageLine(goal, ['throttle']);
- throttle.setColor(kGreen);
+ throttle.setColor(GREEN);
const wheel = teleopPlot.addMessageLine(goal, ['wheel']);
- wheel.setColor(kBlue);
+ wheel.setColor(BLUE);
// Drivetrain Control Mode
const modePlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
- currentTop += height / 2;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ currentTop += DEFAULT_HEIGHT / 2;
// TODO(james): Actually add enum support.
modePlot.plot.getAxisLabels().setTitle(
'Drivetrain Mode [POLYDRIVE, MOTION_PROFILE, ' +
'SPLINE_FOLLOWER, LINE_FOLLOWER]');
- modePlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ modePlot.plot.getAxisLabels().setXLabel(TIME);
modePlot.plot.getAxisLabels().setYLabel('ControllerType');
modePlot.plot.setDefaultYRange([-0.1, 3.1]);
const controllerType = modePlot.addMessageLine(goal, ['controller_type']);
controllerType.setDrawLine(false);
- // Drivetrain estimated relative position
+ // Drivetrain Status estimated relative position
const positionPlot = aosPlotter.addPlot(element, [0, currentTop],
- [width, height]);
- currentTop += height;
+ [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
positionPlot.plot.getAxisLabels().setTitle("Estimated Relative Position " +
"of the Drivetrain");
- positionPlot.plot.getAxisLabels().setXLabel("Monotonic Time (sec)");
+ positionPlot.plot.getAxisLabels().setXLabel(TIME);
positionPlot.plot.getAxisLabels().setYLabel("Relative Position (m)");
const leftPosition =
positionPlot.addMessageLine(status, ["estimated_left_position"]);
- leftPosition.setColor(kRed);
+ leftPosition.setColor(RED);
const rightPosition =
positionPlot.addMessageLine(status, ["estimated_right_position"]);
- rightPosition.setColor(kGreen);
+ rightPosition.setColor(GREEN);
const leftPositionGoal =
positionPlot.addMessageLine(status, ["profiled_left_position_goal"]);
- leftPositionGoal.setColor(kBlue);
+ leftPositionGoal.setColor(BLUE);
const rightPositionGoal =
positionPlot.addMessageLine(status, ["profiled_right_position_goal"]);
- rightPositionGoal.setColor(kPink);
+ rightPositionGoal.setColor(PINK);
+ const leftEncoder = positionPlot.addMessageLine(position, ["left_encoder"]);
+ leftEncoder.setColor(BROWN);
+ const rightEncoder = positionPlot.addMessageLine(position, ["right_encoder"]);
+ rightEncoder.setColor(CYAN);
// Drivetrain Output Voltage
const outputPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
outputPlot.plot.getAxisLabels().setTitle('Drivetrain Output');
- outputPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ outputPlot.plot.getAxisLabels().setXLabel(TIME);
outputPlot.plot.getAxisLabels().setYLabel('Voltage (V)');
const leftVoltage = outputPlot.addMessageLine(output, ['left_voltage']);
- leftVoltage.setColor(kRed);
+ leftVoltage.setColor(RED);
const rightVoltage = outputPlot.addMessageLine(output, ['right_voltage']);
- rightVoltage.setColor(kGreen);
+ rightVoltage.setColor(GREEN);
// Voltage Errors
const voltageErrors =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
voltageErrors.plot.getAxisLabels().setTitle('Voltage Errors');
- voltageErrors.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ voltageErrors.plot.getAxisLabels().setXLabel(TIME);
voltageErrors.plot.getAxisLabels().setYLabel('Voltage (V)');
const leftVoltageError =
voltageErrors.addMessageLine(status, ['left_voltage_error']);
- leftVoltageError.setColor(kRed);
+ leftVoltageError.setColor(RED);
const rightVoltageError =
voltageErrors.addMessageLine(status, ['right_voltage_error']);
- rightVoltageError.setColor(kGreen);
+ rightVoltageError.setColor(GREEN);
const ekfLeftVoltageError =
voltageErrors.addMessageLine(status, ['localizer', 'left_voltage_error']);
- ekfLeftVoltageError.setColor(kPink);
+ ekfLeftVoltageError.setColor(PINK);
const ekfRightVoltageError = voltageErrors.addMessageLine(
status, ['localizer', 'right_voltage_error']);
- ekfRightVoltageError.setColor(kCyan);
+ ekfRightVoltageError.setColor(CYAN);
// Sundry components of the output voltages
const otherVoltages =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
otherVoltages.plot.getAxisLabels().setTitle('Other Voltage Components');
- otherVoltages.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ otherVoltages.plot.getAxisLabels().setXLabel(TIME);
otherVoltages.plot.getAxisLabels().setYLabel('Voltage (V)');
const ffLeftVoltage = otherVoltages.addMessageLine(
status, ['poly_drive_logging', 'ff_left_voltage']);
- ffLeftVoltage.setColor(kRed);
+ ffLeftVoltage.setColor(RED);
ffLeftVoltage.setPointSize(0);
const ffRightVoltage = otherVoltages.addMessageLine(
status, ['poly_drive_logging', 'ff_right_voltage']);
- ffRightVoltage.setColor(kGreen);
+ ffRightVoltage.setColor(GREEN);
ffRightVoltage.setPointSize(0);
const uncappedLeftVoltage =
otherVoltages.addMessageLine(status, ['uncapped_left_voltage']);
- uncappedLeftVoltage.setColor(kRed);
+ uncappedLeftVoltage.setColor(RED);
uncappedLeftVoltage.setDrawLine(false);
const uncappedRightVoltage =
otherVoltages.addMessageLine(status, ['uncapped_right_voltage']);
- uncappedRightVoltage.setColor(kGreen);
+ uncappedRightVoltage.setColor(GREEN);
uncappedRightVoltage.setDrawLine(false);
// Drivetrain Velocities
const velocityPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
velocityPlot.plot.getAxisLabels().setTitle('Velocity Plots');
- velocityPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ velocityPlot.plot.getAxisLabels().setXLabel(TIME);
velocityPlot.plot.getAxisLabels().setYLabel('Wheel Velocity (m/s)');
const ssLeftVelocityGoal =
velocityPlot.addMessageLine(status, ['profiled_left_velocity_goal']);
- ssLeftVelocityGoal.setColor(kPink);
+ ssLeftVelocityGoal.setColor(PINK);
ssLeftVelocityGoal.setPointSize(0.0);
const ssRightVelocityGoal =
velocityPlot.addMessageLine(status, ['profiled_right_velocity_goal']);
- ssRightVelocityGoal.setColor(kCyan);
+ ssRightVelocityGoal.setColor(CYAN);
ssRightVelocityGoal.setPointSize(0.0);
const polyLeftVelocity = velocityPlot.addMessageLine(
status, ['poly_drive_logging', 'goal_left_velocity']);
- polyLeftVelocity.setColor(kPink);
+ polyLeftVelocity.setColor(PINK);
polyLeftVelocity.setDrawLine(false);
const polyRightVelocity = velocityPlot.addMessageLine(
status, ['poly_drive_logging', 'goal_right_velocity']);
- polyRightVelocity.setColor(kCyan);
+ polyRightVelocity.setColor(CYAN);
polyRightVelocity.setDrawLine(false);
const splineLeftVelocity = velocityPlot.addMessageLine(
status, ['trajectory_logging', 'left_velocity']);
- splineLeftVelocity.setColor(kRed);
+ splineLeftVelocity.setColor(RED);
splineLeftVelocity.setDrawLine(false);
const splineRightVelocity = velocityPlot.addMessageLine(
status, ['trajectory_logging', 'right_velocity']);
- splineRightVelocity.setColor(kGreen);
+ splineRightVelocity.setColor(GREEN);
splineRightVelocity.setDrawLine(false);
const leftVelocity =
velocityPlot.addMessageLine(status, ['estimated_left_velocity']);
- leftVelocity.setColor(kRed);
+ leftVelocity.setColor(RED);
const rightVelocity =
velocityPlot.addMessageLine(status, ['estimated_right_velocity']);
- rightVelocity.setColor(kGreen);
+ rightVelocity.setColor(GREEN);
const ekfLeftVelocity =
velocityPlot.addMessageLine(status, ['localizer', 'left_velocity']);
- ekfLeftVelocity.setColor(kRed);
+ ekfLeftVelocity.setColor(RED);
ekfLeftVelocity.setPointSize(0.0);
const ekfRightVelocity =
velocityPlot.addMessageLine(status, ['localizer', 'right_velocity']);
- ekfRightVelocity.setColor(kGreen);
+ ekfRightVelocity.setColor(GREEN);
ekfRightVelocity.setPointSize(0.0);
// Heading
- const yawPlot = aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ const yawPlot = aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
yawPlot.plot.getAxisLabels().setTitle('Robot Yaw');
- yawPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ yawPlot.plot.getAxisLabels().setXLabel(TIME);
yawPlot.plot.getAxisLabels().setYLabel('Yaw (rad)');
const splineYaw =
yawPlot.addMessageLine(status, ['trajectory_logging', 'theta']);
splineYaw.setDrawLine(false);
- splineYaw.setColor(kRed);
+ splineYaw.setColor(RED);
const ekfYaw = yawPlot.addMessageLine(status, ['localizer', 'theta']);
- ekfYaw.setColor(kGreen);
+ ekfYaw.setColor(GREEN);
const downEstimatorYaw =
yawPlot.addMessageLine(status, ['down_estimator', 'yaw']);
- downEstimatorYaw.setColor(kBlue);
+ downEstimatorYaw.setColor(BLUE);
// Pitch/Roll
const orientationPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
orientationPlot.plot.getAxisLabels().setTitle('Orientation');
- orientationPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ orientationPlot.plot.getAxisLabels().setXLabel(TIME);
orientationPlot.plot.getAxisLabels().setYLabel('Angle (rad)');
const roll = orientationPlot.addMessageLine(
status, ['down_estimator', 'lateral_pitch']);
- roll.setColor(kRed);
+ roll.setColor(RED);
roll.setLabel('roll');
const pitch = orientationPlot.addMessageLine(
status, ['down_estimator', 'longitudinal_pitch']);
- pitch.setColor(kGreen);
+ pitch.setColor(GREEN);
pitch.setLabel('pitch');
// Accelerometer/Gravity
const accelPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
accelPlot.plot.getAxisLabels().setTitle('Accelerometer Readings');
accelPlot.plot.getAxisLabels().setYLabel('Acceleration (g)');
accelPlot.plot.getAxisLabels().setXLabel('Monotonic Reading Time (sec)');
const expectedAccelX =
accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_x']);
- expectedAccelX.setColor(kRed);
+ expectedAccelX.setColor(RED);
expectedAccelX.setPointSize(0);
const expectedAccelY =
accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_y']);
- expectedAccelY.setColor(kGreen);
+ expectedAccelY.setColor(GREEN);
expectedAccelY.setPointSize(0);
const expectedAccelZ =
accelPlot.addMessageLine(status, ['down_estimator', 'expected_accel_z']);
- expectedAccelZ.setColor(kBlue);
+ expectedAccelZ.setColor(BLUE);
expectedAccelZ.setPointSize(0);
const gravity_magnitude =
accelPlot.addMessageLine(status, ['down_estimator', 'gravity_magnitude']);
- gravity_magnitude.setColor(kWhite);
+ gravity_magnitude.setColor(WHITE);
gravity_magnitude.setPointSize(0);
const accelX = accelPlot.addMessageLine(imu, ['accelerometer_x']);
- accelX.setColor(kRed);
+ accelX.setColor(RED);
accelX.setDrawLine(false);
const accelY = accelPlot.addMessageLine(imu, ['accelerometer_y']);
- accelY.setColor(kGreen);
+ accelY.setColor(GREEN);
accelY.setDrawLine(false);
const accelZ = accelPlot.addMessageLine(imu, ['accelerometer_z']);
- accelZ.setColor(kBlue);
+ accelZ.setColor(BLUE);
accelZ.setDrawLine(false);
// Absolute X Position
const xPositionPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
xPositionPlot.plot.getAxisLabels().setTitle('X Position');
- xPositionPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ xPositionPlot.plot.getAxisLabels().setXLabel(TIME);
xPositionPlot.plot.getAxisLabels().setYLabel('X Position (m)');
const localizerX = xPositionPlot.addMessageLine(status, ['x']);
- localizerX.setColor(kRed);
+ localizerX.setColor(RED);
const splineX =
xPositionPlot.addMessageLine(status, ['trajectory_logging', 'x']);
- splineX.setColor(kGreen);
+ splineX.setColor(GREEN);
// Absolute Y Position
const yPositionPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
yPositionPlot.plot.getAxisLabels().setTitle('Y Position');
- yPositionPlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ yPositionPlot.plot.getAxisLabels().setXLabel(TIME);
yPositionPlot.plot.getAxisLabels().setYLabel('Y Position (m)');
const localizerY = yPositionPlot.addMessageLine(status, ['y']);
- localizerY.setColor(kRed);
+ localizerY.setColor(RED);
const splineY =
yPositionPlot.addMessageLine(status, ['trajectory_logging', 'y']);
- splineY.setColor(kGreen);
+ splineY.setColor(GREEN);
// Gyro
const gyroPlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height]);
- currentTop += height;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT]);
+ currentTop += DEFAULT_HEIGHT;
gyroPlot.plot.getAxisLabels().setTitle('Gyro Readings');
gyroPlot.plot.getAxisLabels().setYLabel('Angular Velocity (rad / sec)');
gyroPlot.plot.getAxisLabels().setXLabel('Monotonic Reading Time (sec)');
const gyroZeroX =
gyroPlot.addMessageLine(status, ['zeroing', 'gyro_x_average']);
- gyroZeroX.setColor(kRed);
+ gyroZeroX.setColor(RED);
gyroZeroX.setPointSize(0);
gyroZeroX.setLabel('Gyro X Zero');
const gyroZeroY =
gyroPlot.addMessageLine(status, ['zeroing', 'gyro_y_average']);
- gyroZeroY.setColor(kGreen);
+ gyroZeroY.setColor(GREEN);
gyroZeroY.setPointSize(0);
gyroZeroY.setLabel('Gyro Y Zero');
const gyroZeroZ =
gyroPlot.addMessageLine(status, ['zeroing', 'gyro_z_average']);
- gyroZeroZ.setColor(kBlue);
+ gyroZeroZ.setColor(BLUE);
gyroZeroZ.setPointSize(0);
gyroZeroZ.setLabel('Gyro Z Zero');
const gyroX = gyroPlot.addMessageLine(imu, ['gyro_x']);
- gyroX.setColor(kRed);
+ gyroX.setColor(RED);
const gyroY = gyroPlot.addMessageLine(imu, ['gyro_y']);
- gyroY.setColor(kGreen);
+ gyroY.setColor(GREEN);
const gyroZ = gyroPlot.addMessageLine(imu, ['gyro_z']);
- gyroZ.setColor(kBlue);
+ gyroZ.setColor(BLUE);
// IMU States
const imuStatePlot =
- aosPlotter.addPlot(element, [0, currentTop], [width, height / 2]);
- currentTop += height / 2;
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ currentTop += DEFAULT_HEIGHT / 2;
imuStatePlot.plot.getAxisLabels().setTitle('IMU State');
- imuStatePlot.plot.getAxisLabels().setXLabel('Monotonic Time (sec)');
+ imuStatePlot.plot.getAxisLabels().setXLabel(TIME);
imuStatePlot.plot.setDefaultYRange([-0.1, 1.1]);
const zeroedLine = imuStatePlot.addMessageLine(status, ['zeroing', 'zeroed']);
- zeroedLine.setColor(kRed);
+ zeroedLine.setColor(RED);
zeroedLine.setDrawLine(false);
zeroedLine.setLabel('IMU Zeroed');
const faultedLine =
imuStatePlot.addMessageLine(status, ['zeroing', 'faulted']);
- faultedLine.setColor(kGreen);
+ faultedLine.setColor(GREEN);
faultedLine.setPointSize(0);
faultedLine.setLabel('IMU Faulted');
}
diff --git a/frc971/control_loops/drivetrain/robot_state_plotter.ts b/frc971/control_loops/drivetrain/robot_state_plotter.ts
new file mode 100644
index 0000000..f42c50b
--- /dev/null
+++ b/frc971/control_loops/drivetrain/robot_state_plotter.ts
@@ -0,0 +1,66 @@
+// Provides a plot for debugging robot state-related issues.
+import {AosPlotter} from 'org_frc971/aos/network/www/aos_plotter';
+import * as proxy from 'org_frc971/aos/network/www/proxy';
+
+import Connection = proxy.Connection;
+
+const TIME = AosPlotter.TIME;
+const DEFAULT_WIDTH = AosPlotter.DEFAULT_WIDTH;
+const DEFAULT_HEIGHT = AosPlotter.DEFAULT_HEIGHT;
+const RED = AosPlotter.RED;
+const GREEN = AosPlotter.GREEN;
+const BLUE = AosPlotter.BLUE;
+const BROWN = AosPlotter.BROWN;
+const PINK = AosPlotter.PINK;
+const CYAN = AosPlotter.CYAN;
+const WHITE = AosPlotter.WHITE;
+
+export function plotRobotState(conn: Connection, element: Element) : void {
+ const aosPlotter = new AosPlotter(conn);
+ const robotState = aosPlotter.addMessageSource('/aos', 'aos.RobotState');
+ const joystickState = aosPlotter.addMessageSource('/aos', 'aos.JoystickState');
+
+ var currentTop = 0;
+
+ // Robot Enabled/Disabled and Mode
+ const robotStatePlot =
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ currentTop += DEFAULT_HEIGHT / 2;
+ robotStatePlot.plot.getAxisLabels().setTitle('Robot State');
+ robotStatePlot.plot.getAxisLabels().setXLabel(TIME);
+ robotStatePlot.plot.getAxisLabels().setYLabel('bool');
+ robotStatePlot.plot.setDefaultYRange([-0.1, 1.1]);
+
+ const testMode = robotStatePlot.addMessageLine(joystickState, ['test_mode']);
+ testMode.setColor(BLUE);
+ testMode.setPointSize(0.0);
+ const autoMode = robotStatePlot.addMessageLine(joystickState, ['autonomous']);
+ autoMode.setColor(RED);
+ autoMode.setPointSize(0.0);
+
+ const brownOut = robotStatePlot.addMessageLine(robotState, ['browned_out']);
+ brownOut.setColor(BROWN);
+ brownOut.setDrawLine(false);
+ const enabled = robotStatePlot.addMessageLine(joystickState, ['enabled']);
+ enabled.setColor(GREEN);
+ enabled.setDrawLine(false);
+
+ // Battery Voltage
+ const batteryPlot =
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ currentTop += DEFAULT_HEIGHT / 2;
+ batteryPlot.plot.getAxisLabels().setTitle('Battery Voltage');
+ batteryPlot.plot.getAxisLabels().setXLabel(TIME);
+ batteryPlot.plot.getAxisLabels().setYLabel('Voltage (V)');
+
+ batteryPlot.addMessageLine(robotState, ['voltage_battery']);
+
+ // PID of process reading sensors
+ const readerPidPlot =
+ aosPlotter.addPlot(element, [0, currentTop], [DEFAULT_WIDTH, DEFAULT_HEIGHT / 2]);
+ currentTop += DEFAULT_HEIGHT / 2;
+ readerPidPlot.plot.getAxisLabels().setTitle("PID of Process Reading Sensors");
+ readerPidPlot.plot.getAxisLabels().setXLabel(TIME);
+ readerPidPlot.plot.getAxisLabels().setYLabel("wpilib_interface Process ID");
+ readerPidPlot.addMessageLine(robotState, ["reader_pid"]);
+}