From 8fdbed4d296ebe9cf3b71e5b3cd41caa373d6c70 Mon Sep 17 00:00:00 2001 From: Noah Schroeder Date: Thu, 22 Feb 2024 11:33:52 -0600 Subject: [PATCH] feat: add ability to add all loggable types to metadata --- .../littletonrobotics/junction/Logger.java | 314 +++++++++++++++++- 1 file changed, 298 insertions(+), 16 deletions(-) diff --git a/junction/core/src/org/littletonrobotics/junction/Logger.java b/junction/core/src/org/littletonrobotics/junction/Logger.java index 84d50200..62c932cd 100644 --- a/junction/core/src/org/littletonrobotics/junction/Logger.java +++ b/junction/core/src/org/littletonrobotics/junction/Logger.java @@ -62,8 +62,8 @@ public class Logger { private static boolean running = false; private static long cycleCount = 0; private static LogTable entry = new LogTable(0); + private static LogTable metadataTable = new LogTable(0); private static LogTable outputTable; - private static Map metadata = new HashMap<>(); private static ConsoleSource console; private static List dashboardInputs = new ArrayList<>(); private static Supplier urclSupplier = null; @@ -130,18 +130,7 @@ public static void registerURCL(Supplier logSupplier) { urclSupplier = logSupplier; } - /** - * Records a metadata value. This method only works during setup before starting - * to log, then data will be recorded during the first cycle. - * - * @param key The name used to identify this metadata field. - * @param value The value of the metadata field. - */ - public static void recordMetadata(String key, String value) { - if (!running) { - metadata.put(key, value); - } - } + /** * Causes the timestamp returned by "Timer.getFPGATimestamp()" and similar to @@ -195,9 +184,10 @@ public static void start() { } // Record metadata - LogTable metadataTable = entry.getSubtable(replaySource == null ? "RealMetadata" : "ReplayMetadata"); - for (Map.Entry item : metadata.entrySet()) { - metadataTable.put(item.getKey(), item.getValue()); + LogTable entryMetaTable = entry.getSubtable(replaySource == null ? "RealMetadata" : "ReplayMetadata"); + + for (Map.Entry item : metadataTable.getAll(false).entrySet()) { + entryMetaTable.put(item.getKey(), item.getValue()); } // Start receiver thread @@ -799,4 +789,296 @@ public static void recordOutput(String key, Mechanism2d value) { } } } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, byte[] value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, boolean value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, int value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, long value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, float value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, double value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, String value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static > void recordMetadata(String key, E value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static > void recordMetadata(String key, Measure value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, boolean[] value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, int[] value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, long[] value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, float[] value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, double[] value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, String[] value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + *

+ * This method serializes a single object as a struct. Example usage: + * {@code recordMetadata("MyPose", Pose2d.struct, new Pose2d())} + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + public static void recordMetadata(String key, Struct struct, T value) { + if (running) { + metadataTable.put(key, struct, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + *

+ * This method serializes an array of objects as a struct. Example usage: + * {@code + * recordMetadata("MyPoses", Pose2d.struct, new Pose2d(), new Pose2d()); + * recordMetadata("MyPoses", Pose2d.struct, new Pose2d[] {new Pose2d(), new + * Pose2d()}); + * } + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + @SuppressWarnings("unchecked") + public static void recordMetadata(String key, Struct struct, T... value) { + if (running) { + metadataTable.put(key, struct, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + *

+ * This method serializes a single object as a protobuf. Protobuf should only be + * used for objects that do not support struct serialization. Example usage: + * {@code recordMetadata("MyPose", Pose2d.proto, new Pose2d())} + * + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + @SuppressWarnings("unchecked") + public static > void recordMetadata(String key, Protobuf proto, + T value) { + if (running) { + metadataTable.put(key, proto, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + *

+ * This method serializes a single object as a struct or protobuf automatically. + * Struct is preferred if both methods are supported. + * + * @param T The type + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + @SuppressWarnings("unchecked") + public static void recordMetadata(String key, T value) { + if (running) { + metadataTable.put(key, value); + } + } + + /** + * Records a metadata value. This method only works during setup before starting + * to log, then data will be recorded during the first cycle. + * + *

+ * This method serializes an array of objects as a struct automatically. + * Top-level protobuf arrays are not supported. + * + * @param T The type + * @param key The name used to identify this metadata field. + * @param value The value of the metadata field. + */ + @SuppressWarnings("unchecked") + public static void recordMetadata(String key, T... value) { + if (running) { + metadataTable.put(key, value); + } + } }