Merge "Delete old Python plotter"
diff --git a/frc971/analysis/BUILD b/frc971/analysis/BUILD
index f56c429..7cb0b4d 100644
--- a/frc971/analysis/BUILD
+++ b/frc971/analysis/BUILD
@@ -6,13 +6,6 @@
load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library", "flatbuffer_ts_library")
load("//aos:config.bzl", "aos_config")
-py_library(
- name = "python_init",
- srcs = ["__init__.py"],
- target_compatible_with = ["@platforms//os:linux"],
- deps = ["//frc971:python_init"],
-)
-
cc_binary(
name = "py_log_reader.so",
srcs = ["py_log_reader.cc"],
@@ -40,36 +33,6 @@
deps = ["//aos:configuration_fbs_python"],
)
-py_proto_library(
- name = "plot_config_proto",
- srcs = ["plot_config.proto"],
- target_compatible_with = ["@platforms//os:linux"],
-)
-
-py_binary(
- name = "plot",
- srcs = ["plot.py"],
- data = [
- ":py_log_reader.so",
- ] + glob(["plot_configs/**"]),
- target_compatible_with = ["@platforms//os:linux"],
- deps = [
- ":plot_config_proto",
- ":python_init",
- "@matplotlib_repo//:matplotlib3",
- ],
-)
-
-py_test(
- name = "plot_test",
- srcs = ["plot_test.py"],
- data = [
- "@sample_logfile//file",
- ],
- target_compatible_with = ["@platforms//os:linux"],
- deps = [":plot"],
-)
-
ts_library(
name = "plot_index",
srcs = ["plot_index.ts"],
diff --git a/frc971/analysis/__init__.py b/frc971/analysis/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/frc971/analysis/__init__.py
+++ /dev/null
diff --git a/frc971/analysis/drivetrain_down_stripped b/frc971/analysis/drivetrain_down_stripped
deleted file mode 100644
index 3b3e43d..0000000
--- a/frc971/analysis/drivetrain_down_stripped
+++ /dev/null
@@ -1,4 +0,0 @@
-drivetrain.stripped output left_voltage
-drivetrain.stripped output right_voltage
-
-drivetrain.stripped status ground_angle
diff --git a/frc971/analysis/drivetrain_plot_stripped b/frc971/analysis/drivetrain_plot_stripped
deleted file mode 100644
index 3c24485..0000000
--- a/frc971/analysis/drivetrain_plot_stripped
+++ /dev/null
@@ -1,20 +0,0 @@
-drivetrain.stripped output left_voltage
-drivetrain.stripped output right_voltage
-
-drivetrain.stripped status profiled_left_position_goal
-drivetrain.stripped status profiled_right_position_goal
-drivetrain.stripped status profiled_left_velocity_goal
-drivetrain.stripped status profiled_right_velocity_goal
-
-drivetrain.stripped status estimated_left_position
-drivetrain.stripped status estimated_right_position
-drivetrain.stripped status estimated_left_velocity
-drivetrain.stripped status estimated_right_velocity
-
-drivetrain.stripped goal left_goal
-drivetrain.stripped goal right_goal
-
-drivetrain.stripped status left_voltage_error -m 0.1
-drivetrain.stripped status right_voltage_error -m 0.1
-
-drivetrain.stripped using accelerometer_y -m -10
diff --git a/frc971/analysis/drivetrain_test_plot b/frc971/analysis/drivetrain_test_plot
deleted file mode 100644
index 0b2cc2a..0000000
--- a/frc971/analysis/drivetrain_test_plot
+++ /dev/null
@@ -1,16 +0,0 @@
-drivetrain_lib_test output left_voltage
-drivetrain_lib_test output right_voltage
-
-drivetrain_lib_test status estimated_left_position
-drivetrain_lib_test status estimated_right_position
-drivetrain_lib_test status estimated_left_velocity
-drivetrain_lib_test status estimated_right_velocity
-
-drivetrain_lib_test goal left_goal
-drivetrain_lib_test goal right_goal
-drivetrain_lib_test status profiled_left_position_goal
-drivetrain_lib_test status profiled_right_position_goal
-drivetrain_lib_test status profiled_left_velocity_goal
-drivetrain_lib_test status profiled_right_velocity_goal
-
-robot_state browned_out
diff --git a/frc971/analysis/plot.py b/frc971/analysis/plot.py
deleted file mode 100644
index efe86f4..0000000
--- a/frc971/analysis/plot.py
+++ /dev/null
@@ -1,306 +0,0 @@
-#!/usr/bin/python3
-# Sample usage:
-# bazel run -c opt //frc971/analysis:plot -- --logfile /tmp/log.fbs --config gyro.pb
-import argparse
-import json
-import os.path
-from pathlib import Path
-import sys
-
-from frc971.analysis.py_log_reader import LogReader
-from frc971.analysis.plot_config_pb2 import PlotConfig, Signal, Line
-from google.protobuf import text_format
-
-import numpy as np
-import matplotlib
-from matplotlib import pyplot as plt
-
-
-class Plotter:
- def __init__(self, plot_config: PlotConfig, reader: LogReader):
- self.config = plot_config
- self.reader = reader
- # Data streams, indexed by alias.
- self.data = {}
-
- def process_logfile(self):
- aliases = set()
- for channel in self.config.channel:
- if channel.alias in aliases:
- raise ValueError("Duplicate alias " + channel.alias)
- if not self.reader.subscribe(channel.name, channel.type):
- print("Warning: No such channel with name " + channel.name +
- " and type " + channel.type)
- continue
- aliases.add(channel.alias)
-
- self.reader.process()
-
- for channel in self.config.channel:
- self.data[channel.alias] = []
- if channel.alias not in aliases:
- print("Unable to plot channel alias " + channel.alias)
- continue
- for message in self.reader.get_data_for_channel(
- channel.name, channel.type):
- valid_json = message[2].replace('nan', '"nan"')
- valid_json = valid_json.replace(' inf', ' "inf"')
- valid_json = valid_json.replace('-inf', '"-inf"')
- try:
- parsed_json = json.loads(valid_json)
- except json.decoder.JSONDecodeError as ex:
- print("JSON Decode failed:")
- print(valid_json)
- raise ex
- self.data[channel.alias].append(
- (message[0], message[1], parsed_json))
- self.calculate_signals()
-
- def calculate_down_estimator_signals(self):
- if 'DrivetrainStatus' in self.data:
- # Calculates a rolling mean of the acceleration output from
- # the down estimator.
- entries = []
- buffer_len = 100
- last_100_accels = np.zeros((buffer_len, 3))
- accels_next_row = 0
- for entry in self.data['DrivetrainStatus']:
- msg = entry[2]
- new_msg = {}
- if 'down_estimator' not in msg:
- continue
- down_estimator = msg['down_estimator']
- new_msg['down_estimator'] = {}
- accel_x = 'accel_x'
- accel_y = 'accel_y'
- accel_z = 'accel_z'
- if (accel_x in down_estimator and accel_y in down_estimator
- and accel_x in down_estimator):
- last_100_accels[accels_next_row, :] = [
- down_estimator[accel_x], down_estimator[accel_y],
- down_estimator[accel_z]
- ]
-
- accels_next_row += 1
- accels_next_row = accels_next_row % buffer_len
- mean_accels = np.mean(last_100_accels, axis=0)
- new_msg['down_estimator'][
- 'accel_x_rolling_mean'] = mean_accels[0]
- new_msg['down_estimator'][
- 'accel_y_rolling_mean'] = mean_accels[1]
- new_msg['down_estimator'][
- 'accel_z_rolling_mean'] = mean_accels[2]
- entries.append((entry[0], entry[1], new_msg))
- if 'CalcDrivetrainStatus' in self.data:
- raise RuntimeError(
- 'CalcDrivetrainStatus is already a member of data.')
- self.data['CalcDrivetrainStatus'] = entries
-
- def calculate_imu_signals(self):
- if 'IMU' in self.data:
- entries = []
- # Calculates a rolling mean of the raw output from the IMU.
- buffer_len = 1000
- last_1000_accels = np.zeros((buffer_len, 3))
- accels_next_row = 0
- last_1000_gyros = np.zeros((buffer_len, 3))
- gyros_next_row = 0
- for entry in self.data['IMU']:
- for msg in entry[2]['readings']:
- accel_x = 'accelerometer_x'
- accel_y = 'accelerometer_y'
- accel_z = 'accelerometer_z'
- gyro_x = 'gyro_x'
- gyro_y = 'gyro_y'
- gyro_z = 'gyro_z'
- temp = 'temperature'
- new_msg = {}
- if temp in msg:
- new_msg[temp] = msg[temp]
- if accel_x in msg and accel_y in msg and accel_x in msg:
- last_1000_accels[accels_next_row, :] = [
- msg[accel_x], msg[accel_y], msg[accel_z]
- ]
- total_acceleration = np.linalg.norm(
- last_1000_accels[accels_next_row, :])
- new_msg['total_acceleration'] = total_acceleration
-
- accels_next_row += 1
- accels_next_row = accels_next_row % buffer_len
- std_accels = np.std(last_1000_accels, axis=0)
- new_msg['accel_x_rolling_std'] = std_accels[0]
- new_msg['accel_y_rolling_std'] = std_accels[1]
- new_msg['accel_z_rolling_std'] = std_accels[2]
- mean_accels = np.mean(last_1000_accels, axis=0)
- new_msg['accel_x_rolling_mean'] = mean_accels[0]
- new_msg['accel_y_rolling_mean'] = mean_accels[1]
- new_msg['accel_z_rolling_mean'] = mean_accels[2]
- new_msg[accel_x] = msg[accel_x]
- new_msg[accel_y] = msg[accel_y]
- new_msg[accel_z] = msg[accel_z]
- if gyro_x in msg and gyro_y in msg and gyro_z in msg:
- last_1000_gyros[gyros_next_row, :] = [
- msg[gyro_x], msg[gyro_y], msg[gyro_z]
- ]
- gyros_next_row += 1
- gyros_next_row = gyros_next_row % buffer_len
- std_gyros = np.std(last_1000_gyros, axis=0)
- new_msg['gyro_x_rolling_std'] = std_gyros[0]
- new_msg['gyro_y_rolling_std'] = std_gyros[1]
- new_msg['gyro_z_rolling_std'] = std_gyros[2]
- mean_gyros = np.mean(last_1000_gyros, axis=0)
- new_msg['gyro_x_rolling_mean'] = mean_gyros[0]
- new_msg['gyro_y_rolling_mean'] = mean_gyros[1]
- new_msg['gyro_z_rolling_mean'] = mean_gyros[2]
- new_msg[gyro_x] = msg[gyro_x]
- new_msg[gyro_y] = msg[gyro_y]
- new_msg[gyro_z] = msg[gyro_z]
- timestamp = 'monotonic_timestamp_ns'
- if timestamp in msg:
- timestamp_sec = msg[timestamp] * 1e-9
- new_msg['monotonic_timestamp_sec'] = timestamp_sec
- entries.append((entry[0], entry[1], new_msg))
- if 'CalcIMU' in self.data:
- raise RuntimeError('CalcIMU is already a member of data.')
- self.data['CalcIMU'] = entries
-
- def calculate_signals(self):
- """Calculate any derived signals for plotting.
-
- See calculate_imu_signals for an example, but the basic idea is that
- for any data that is read in from the logfile, we may want to calculate
- some derived signals--possibly as simple as doing unit conversions,
- or more complicated version where we do some filtering or the such.
- The way this will work is that the calculate_* functions will, if the
- raw data is available, calculate the derived signals and place them into
- fake "messages" with an alias of "Calc*". E.g., we currently calculate
- an overall magnitude for the accelerometer readings, which is helpful
- to understanding how some internal filters work."""
- self.calculate_imu_signals()
- self.calculate_down_estimator_signals()
-
- def extract_field(self, message: dict, field: str):
- """Extracts a field with the given name from the message.
-
- message will be a dictionary with field names as the keys and then
- values, lists, or more dictionaries as the values. field is the full
- path to the field to extract, with periods separating sub-messages."""
- field_path = field.split('.')
- value = message
- for name in field_path:
- # If the value wasn't populated in a given message, fill in
- # NaN rather than crashing.
- if name in value:
- value = value[name]
- else:
- return None
- # Catch NaNs and convert them to floats.
- return float(value)
-
- def plot_line(self, axes: matplotlib.axes.Axes, line: Line):
- if not line.HasField('y_signal'):
- raise ValueError("No y_channel specified for line.")
- y_signal = line.y_signal
- if not y_signal.channel in self.data:
- raise ValueError("No channel alias " + y_signal.channel)
- x_signal = line.x_signal if line.HasField('x_signal') else None
- if x_signal is not None and not x_signal.channel in self.data:
- raise ValueError("No channel alias " + x_signal.channel)
- y_messages = self.data[y_signal.channel]
- x_messages = self.data[
- x_signal.channel] if x_signal is not None else None
- if x_messages is not None and len(x_messages) != len(y_messages):
- raise ValueError(
- "X and Y signal lengths don't match. X channel is " +
- x_signal.channel + " Y channel is " + y_signal.channel)
- x_data = []
- y_data = []
- for ii in range(len(y_messages)):
- y_entry = y_messages[ii]
- if x_signal is None:
- x_data.append(y_entry[0] * 1e-9)
- else:
- x_entry = x_messages[ii]
- x_data.append(self.extract_field(x_entry[2], x_signal.field))
- y_data.append(self.extract_field(y_entry[2], y_signal.field))
- if x_data[-1] is None and y_data[-1] is not None:
- raise ValueError(
- "Only one of the x and y signals is present. X " +
- x_signal.channel + "." + x_signal.field + " Y " +
- y_signal.channel + "." + y_signal.field)
- label_name = y_signal.channel + "." + y_signal.field
- axes.plot(x_data, y_data, marker='o', label=label_name)
-
- def plot(self):
- shared_axis = None
- for figure_config in self.config.figure:
- fig = plt.figure()
- num_subplots = len(figure_config.axes)
- for ii in range(num_subplots):
- axes_config = figure_config.axes[ii]
- share_axis = axes_config.share_x_axis
- axes = fig.add_subplot(
- num_subplots,
- 1,
- ii + 1,
- sharex=shared_axis if share_axis else None)
- if share_axis and shared_axis is None:
- shared_axis = axes
- for line in axes_config.line:
- self.plot_line(axes, line)
- # Make the legend transparent so we can see behind it.
- legend = axes.legend(framealpha=0.5, loc='upper right')
- axes.set_xlabel(axes_config.xlabel)
- axes.grid(True)
- if axes_config.HasField("ylabel"):
- axes.set_ylabel(axes_config.ylabel)
-
-
-def main(argv):
- parser = argparse.ArgumentParser(
- description="Plot data from an aos logfile.")
- parser.add_argument("--logfile",
- type=str,
- required=True,
- help="Path to the logfile to parse.")
- parser.add_argument("--config",
- type=str,
- required=True,
- help="Name of the plot config to use.")
- parser.add_argument("--config_dir",
- type=str,
- default="frc971/analysis/plot_configs",
- help="Directory to look for plot configs in.")
- args = parser.parse_args(argv[1:])
-
- if not os.path.isdir(args.config_dir):
- print(args.config_dir + " is not a directory.")
- return 1
- config_path = os.path.join(args.config_dir, args.config)
- if not os.path.isfile(config_path):
- print(config_path +
- " does not exist or is not a file--available configs are")
- for file_name in os.listdir(args.config_dir):
- print(os.path.basename(file_name))
- return 1
-
- config = PlotConfig()
- with open(config_path) as config_file:
- text_format.Merge(config_file.read(), config)
-
- if not os.path.isfile(args.logfile):
- print(args.logfile + " is not a file.")
- return 1
-
- reader = LogReader(args.logfile)
-
- plotter = Plotter(config, reader)
- plotter.process_logfile()
- plotter.plot()
- plt.show()
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/frc971/analysis/plot_config.proto b/frc971/analysis/plot_config.proto
deleted file mode 100644
index cd01f73..0000000
--- a/frc971/analysis/plot_config.proto
+++ /dev/null
@@ -1,64 +0,0 @@
-syntax = "proto2";
-
-package frc971.analysis;
-
-// Specification fo a Channel to pull from the logfile. The name and type will
-// be the full name/type of the channel to pull from the logfile. The alias is a
-// shorter, easier to type, name that the rest of the logfile will use to refer
-// to the channel.
-message Channel {
- optional string name = 1;
- optional string type = 2;
- optional string alias = 3;
-}
-
-// A specification for a single signal within a Channel.
-message Signal {
- // Alias for the channel to pull the signal from--this should match an alias
- // specified in one of the Channels.
- optional string channel = 1;
- // Specification of the field to plot. Currently, this only supports simple
- // submessages, using dots. To access, e.g., the "bar" member of the "foo"
- // submessage, field would be "foo.bar". This does not currently support
- // working with repeated fields.
- optional string field = 2;
-}
-
-// A single line to plot.
-message Line {
- // The signal to plot on the y-axis.
- optional Signal y_signal = 1;
- // If set, we will use this signal for the x-axis of the plot. By default, we
- // will use the monotonic sent time of the message. This is helpful for both
- // plotting against non-time based signals (e.g., plotting x/y robot position)
- // as well as plotting against times other than the message sent time (e.g.,
- // for the IMU where the sample capture time is separate from the actual
- // sent time.
- // Note that the x and y signals should have exactly the same number of
- // entries--otherwise, we need to write logic to handle resampling one signal
- // to a different rate.
- optional Signal x_signal = 2;
-}
-
-// Message representing a single pyplot Axes, with specifications for exactly
-// which signals to show in the supplied subplot.
-message Axes {
- repeated Line line = 1;
- optional string ylabel = 2;
- optional string xlabel = 3 [default = "Monotonic Time (sec)"];
- // Whether to share an x-axis with all the other axes.
- optional bool share_x_axis = 4 [default = true];
-}
-
-// Message representing a single pyplot figure.
-message Figure {
- repeated Axes axes = 1;
-}
-
-// This configuration specifies what to plot when reading from a logfile.
-message PlotConfig {
- // List of channels and their aliases to use in the plot.
- repeated Channel channel = 1;
- // Figures to plot.
- repeated Figure figure = 2;
-}
diff --git a/frc971/analysis/plot_configs/down_estimator.pb b/frc971/analysis/plot_configs/down_estimator.pb
deleted file mode 100644
index 48cf2ef..0000000
--- a/frc971/analysis/plot_configs/down_estimator.pb
+++ /dev/null
@@ -1,187 +0,0 @@
-channel {
- name: "/drivetrain"
- type: "frc971.control_loops.drivetrain.Status"
- alias: "DrivetrainStatus"
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.yaw"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.lateral_pitch"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.longitudinal_pitch"
- }
- }
- ylabel: "rad"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.quaternion_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.quaternion_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.quaternion_z"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.quaternion_w"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.accel_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.accel_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.accel_z"
- }
- }
- ylabel: "m/s/s"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.velocity_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.velocity_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.velocity_z"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.position_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.position_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.position_z"
- }
- }
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "zeroing.gyro_x_average"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "zeroing.gyro_y_average"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "zeroing.gyro_z_average"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.expected_accel_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.expected_accel_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.expected_accel_z"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.gravity_magnitude"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "CalcDrivetrainStatus"
- field: "down_estimator.accel_x_rolling_mean"
- }
- }
- line {
- y_signal {
- channel: "CalcDrivetrainStatus"
- field: "down_estimator.accel_y_rolling_mean"
- }
- }
- line {
- y_signal {
- channel: "CalcDrivetrainStatus"
- field: "down_estimator.accel_z_rolling_mean"
- }
- }
- }
-}
diff --git a/frc971/analysis/plot_configs/drivetrain.pb b/frc971/analysis/plot_configs/drivetrain.pb
deleted file mode 100644
index 0335da8..0000000
--- a/frc971/analysis/plot_configs/drivetrain.pb
+++ /dev/null
@@ -1,463 +0,0 @@
-channel {
- name: "/aos"
- type: "aos.JoystickState"
- alias: "JoystickState"
-}
-channel {
- name: "/aos"
- type: "aos.RobotState"
- alias: "RobotState"
-}
-channel {
- name: "/drivetrain"
- type: "frc971.control_loops.drivetrain.Goal"
- alias: "Goal"
-}
-channel {
- name: "/drivetrain"
- type: "frc971.control_loops.drivetrain.Status"
- alias: "Status"
-}
-channel {
- name: "/drivetrain"
- type: "frc971.control_loops.drivetrain.Output"
- alias: "Output"
-}
-channel {
- name: "/drivetrain"
- type: "frc971.IMUValues"
- alias: "IMU"
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "JoystickState"
- field: "test_mode"
- }
- }
- line {
- y_signal {
- channel: "JoystickState"
- field: "autonomous"
- }
- }
- line {
- y_signal {
- channel: "RobotState"
- field: "browned_out"
- }
- }
- line {
- y_signal {
- channel: "JoystickState"
- field: "enabled"
- }
- }
- ylabel: "[bool]"
- }
- axes {
- line {
- y_signal {
- channel: "RobotState"
- field: "voltage_battery"
- }
- }
- ylabel: "[V]"
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "line_follow_logging.frozen"
- }
- }
- line {
- y_signal {
- channel: "Goal"
- field: "quickturn"
- }
- }
- ylabel: "[bool]"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "poly_drive_logging.ff_left_voltage"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "poly_drive_logging.ff_right_voltage"
- }
- }
- line {
- y_signal {
- channel: "Output"
- field: "left_voltage"
- }
- }
- line {
- y_signal {
- channel: "Output"
- field: "right_voltage"
- }
- }
- ylabel: "[V]"
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "theta"
- }
- }
- ylabel: "[rad]"
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "robot_speed"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "trajectory_logging.left_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "poly_drive_logging.goal_left_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "estimated_left_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "trajectory_logging.right_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "poly_drive_logging.goal_right_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "estimated_right_velocity"
- }
- }
- ylabel: "[m/s]"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "IMU"
- field: "gyro_x"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "IMU"
- field: "gyro_y"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "IMU"
- field: "gyro_z"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "rad / sec"
- }
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "total_acceleration"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "IMU"
- field: "accelerometer_x"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "IMU"
- field: "accelerometer_y"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "IMU"
- field: "accelerometer_z"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "g"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.yaw"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.lateral_pitch"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.longitudinal_pitch"
- }
- }
- ylabel: "rad"
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.quaternion_x"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.quaternion_y"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.quaternion_z"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.quaternion_w"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.velocity_x"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.velocity_y"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.position_x"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "down_estimator.position_y"
- }
- }
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_x_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_y_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_z_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "g"
- }
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_x_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_y_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_z_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "g"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_x_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_y_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_z_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "rad / sec"
- }
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_x_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_y_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_z_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "rad / sec"
- }
-}
diff --git a/frc971/analysis/plot_configs/gyro.pb b/frc971/analysis/plot_configs/gyro.pb
deleted file mode 100644
index 70c6480..0000000
--- a/frc971/analysis/plot_configs/gyro.pb
+++ /dev/null
@@ -1,238 +0,0 @@
-channel {
- name: "/drivetrain"
- type: "frc971.IMUValuesBatch"
- alias: "IMU"
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_x"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_y"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_z"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "rad / sec"
- }
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "total_acceleration"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accelerometer_x"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accelerometer_y"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accelerometer_z"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "g"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_x_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_y_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_z_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "g"
- }
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_x_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_y_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "accel_z_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "g"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_x_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_y_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_z_rolling_mean"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "rad / sec"
- }
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_x_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_y_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- line {
- y_signal {
- channel: "CalcIMU"
- field: "gyro_z_rolling_std"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "rad / sec"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "CalcIMU"
- field: "temperature"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "C"
- }
-}
diff --git a/frc971/analysis/plot_configs/gyro_temp.pb b/frc971/analysis/plot_configs/gyro_temp.pb
deleted file mode 100644
index 02c8c3b..0000000
--- a/frc971/analysis/plot_configs/gyro_temp.pb
+++ /dev/null
@@ -1,21 +0,0 @@
-channel {
- name: "/drivetrain"
- type: "frc971.IMUValues"
- alias: "IMU"
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "IMU"
- field: "temperature"
- }
- x_signal {
- channel: "CalcIMU"
- field: "monotonic_timestamp_sec"
- }
- }
- ylabel: "C"
- }
-}
diff --git a/frc971/analysis/plot_configs/localizer.pb b/frc971/analysis/plot_configs/localizer.pb
deleted file mode 100644
index 6181e11..0000000
--- a/frc971/analysis/plot_configs/localizer.pb
+++ /dev/null
@@ -1,322 +0,0 @@
-channel {
- name: "/drivetrain"
- type: "frc971.control_loops.drivetrain.Status"
- alias: "DrivetrainStatus"
-}
-channel {
- name: "/drivetrain/truth"
- type: "frc971.control_loops.drivetrain.Status"
- alias: "DrivetrainTruthStatus"
-}
-channel {
- name: "/drivetrain"
- type: "frc971.control_loops.drivetrain.Position"
- alias: "DrivetrainPosition"
-}
-channel {
- name: "/drivetrain"
- type: "frc971.control_loops.drivetrain.Output"
- alias: "DrivetrainOutput"
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.y"
- }
- x_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainTruthStatus"
- field: "y"
- }
- x_signal {
- channel: "DrivetrainTruthStatus"
- field: "x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "y"
- }
- x_signal {
- channel: "DrivetrainStatus"
- field: "x"
- }
- }
- share_x_axis: false
- xlabel: "x (m)"
- ylabel: "y (m)"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.yaw"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.theta"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainTruthStatus"
- field: "theta"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.theta"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.lateral_pitch"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.longitudinal_pitch"
- }
- }
- ylabel: "rad"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.position_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.position_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainTruthStatus"
- field: "x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainTruthStatus"
- field: "y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.y"
- }
- }
- ylabel: "m"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.velocity_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.velocity_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.longitudinal_velocity_offset"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.lateral_velocity"
- }
- }
- ylabel: "m/s"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.accel_x"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.accel_y"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "down_estimator.accel_z"
- }
- }
- ylabel: "m/s/s"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.left_velocity"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "trajectory_logging.right_velocity"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.left_velocity"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.right_velocity"
- }
- }
- ylabel: "m/s"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainPosition"
- field: "left_encoder"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainPosition"
- field: "right_encoder"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.left_encoder"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.right_encoder"
- }
- }
- ylabel: "m"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.angular_error"
- }
- }
- ylabel: "rad / sec"
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "DrivetrainOutput"
- field: "left_voltage"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainOutput"
- field: "right_voltage"
- }
- }
- ylabel: "V"
- }
- axes {
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "left_voltage_error"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "right_voltage_error"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.left_voltage_error"
- }
- }
- line {
- y_signal {
- channel: "DrivetrainStatus"
- field: "localizer.right_voltage_error"
- }
- }
- ylabel: "V"
- }
-}
diff --git a/frc971/analysis/plot_configs/turret_plot.pb b/frc971/analysis/plot_configs/turret_plot.pb
deleted file mode 100644
index 64c5f22..0000000
--- a/frc971/analysis/plot_configs/turret_plot.pb
+++ /dev/null
@@ -1,128 +0,0 @@
-channel {
- name: "/roborio/aos"
- type: "aos.JoystickState"
- alias: "JoystickState"
-}
-channel {
- name: "/superstructure"
- type: "y2020.control_loops.superstructure.Status"
- alias: "Status"
-}
-channel {
- name: "/superstructure"
- type: "y2020.control_loops.superstructure.Output"
- alias: "Output"
-}
-channel {
- name: "/superstructure"
- type: "y2020.control_loops.superstructure.Position"
- alias: "Position"
-}
-channel {
- name: "/superstructure"
- type: "y2020.control_loops.superstructure.Goal"
- alias: "Goal"
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "turret.goal_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "turret.unprofiled_goal_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "aimer.turret_velocity"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "turret.velocity"
- }
- }
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "turret.goal_position"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "turret.unprofiled_goal_position"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "aimer.turret_position"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "turret.position"
- }
- }
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "aimer.aiming_for_inner_port"
- }
- }
-# line {
-# y_signal {
-# channel: "JoystickState"
-# field: "alliance"
-# }
-# }
- }
- axes {
- line {
- y_signal {
- channel: "Status"
- field: "aimer.shot_distance"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "aimer.target_distance"
- }
- }
- }
-}
-
-figure {
- axes {
- line {
- y_signal {
- channel: "Output"
- field: "turret_voltage"
- }
- }
- line {
- y_signal {
- channel: "Status"
- field: "turret.voltage_error"
- }
- }
- }
-}
diff --git a/frc971/analysis/plot_test.py b/frc971/analysis/plot_test.py
deleted file mode 100644
index 1c57ae2..0000000
--- a/frc971/analysis/plot_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/python3
-import unittest
-
-import matplotlib
-# Use a non-interactive backend so that the test can actually run...
-matplotlib.use('Agg')
-
-import frc971.analysis.plot
-
-
-class PlotterTest(unittest.TestCase):
- def test_plotter(self):
- """Basic test that makes sure that we can run the test without crashing."""
- self.assertEqual(0,
- frc971.analysis.plot.main([
- "binary", "--logfile",
- "external/sample_logfile/file/log.fbs",
- "--config", "gyro.pb"
- ]))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/frc971/analysis/py_log_reader.cc b/frc971/analysis/py_log_reader.cc
index 5b32ed6..6a6c767 100644
--- a/frc971/analysis/py_log_reader.cc
+++ b/frc971/analysis/py_log_reader.cc
@@ -1,6 +1,11 @@
// This file provides a Python module for reading logfiles. See
// log_reader_test.py for usage.
//
+// NOTE: This code has not been maintained recently, and so is missing key
+// features to support reading multi-node logfiles (namely, it assumes the the
+// logfile is just a single file). Updating this code should not be difficult,
+// but hasn't been needed thus far.
+//
// This reader works by having the user specify exactly what channels they want
// data for. We then process the logfile and store all the data on that channel
// into a list of timestamps + JSON message data. The user can then use an