diff --git a/epilogue-runtime/build.gradle b/epilogue-runtime/build.gradle index fb96095a0a5..303c090c9c7 100644 --- a/epilogue-runtime/build.gradle +++ b/epilogue-runtime/build.gradle @@ -13,4 +13,5 @@ dependencies { api(project(':ntcore')) api(project(':wpiutil')) api(project(':wpiunits')) + api(project(':wpilibj')) } diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java index a35f98d41a4..96111dea531 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/EpilogueConfiguration.java @@ -5,10 +5,9 @@ package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.logging.EpilogueBackend; -import edu.wpi.first.epilogue.logging.NTEpilogueBackend; +import edu.wpi.first.epilogue.logging.NTBackend; import edu.wpi.first.epilogue.logging.errors.ErrorHandler; import edu.wpi.first.epilogue.logging.errors.ErrorPrinter; -import edu.wpi.first.networktables.NetworkTableInstance; import edu.wpi.first.units.measure.Time; /** @@ -22,7 +21,7 @@ public class EpilogueConfiguration { * NetworkTables. NetworkTable data can be mirrored to a log file on disk by calling {@code * DataLogManager.start()} in your {@code robotInit} method. */ - public EpilogueBackend backend = new NTEpilogueBackend(NetworkTableInstance.getDefault()); + public EpilogueBackend backend = new NTBackend(); /** * The period Epilogue will log at. By default this is the period that the robot runs at. This is diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java index 2b5b6b2071b..40cf7a48200 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/FileBackend.java @@ -22,6 +22,7 @@ import edu.wpi.first.util.datalog.StructArrayLogEntry; import edu.wpi.first.util.datalog.StructLogEntry; import edu.wpi.first.util.struct.Struct; +import edu.wpi.first.wpilibj.DataLogManager; import java.util.HashMap; import java.util.Map; import java.util.function.BiFunction; @@ -37,10 +38,20 @@ public class FileBackend implements EpilogueBackend { * * @param dataLog the data log to save data to */ - public FileBackend(DataLog dataLog) { + FileBackend(DataLog dataLog) { this.m_dataLog = requireNonNullParam(dataLog, "dataLog", "FileBackend"); } + /** + * Creates a new file-based backend. + * + * @param enableNtCapture enables capture of networktables data to datalog if true + */ + public FileBackend(boolean enableNtCapture) { + this.m_dataLog = DataLogManager.getLog(); + DataLogManager.logNetworkTables(enableNtCapture); + } + @Override public EpilogueBackend getNested(String path) { return m_subLoggers.computeIfAbsent(path, k -> new NestedBackend(k, this)); diff --git a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTEpilogueBackend.java b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java similarity index 70% rename from epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTEpilogueBackend.java rename to epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java index cf381a2f021..9295a22ac66 100644 --- a/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTEpilogueBackend.java +++ b/epilogue-runtime/src/main/java/edu/wpi/first/epilogue/logging/NTBackend.java @@ -22,13 +22,15 @@ import edu.wpi.first.util.struct.Struct; import java.util.HashMap; import java.util.Map; +import java.util.function.BooleanSupplier; /** * A backend implementation that sends data over network tables. Be careful when using this, since * sending too much data may cause bandwidth or CPU starvation. */ -public class NTEpilogueBackend implements EpilogueBackend { +public class NTBackend implements EpilogueBackend { private final NetworkTableInstance m_nt; + private BooleanSupplier m_disabledSupplier; private final Map m_publishers = new HashMap<>(); private final Map m_nestedBackends = new HashMap<>(); @@ -38,10 +40,32 @@ public class NTEpilogueBackend implements EpilogueBackend { * * @param nt the NetworkTable instance to use to send data to */ - public NTEpilogueBackend(NetworkTableInstance nt) { + NTBackend(NetworkTableInstance nt) { this.m_nt = nt; } + /** Creates a logging backend that sends information to NetworkTables. */ + public NTBackend() { + this.m_nt = NetworkTableInstance.getDefault(); + } + + /** + * Creates a new NTBackend that is disabled whenever the disabledSupplier returns true. + * + * @param disabledSupplier the disable condition for NT logging + * @return a new NTBackend + */ + public NTBackend disableWhen(BooleanSupplier disabledSupplier) { + var newBackend = new NTBackend(this.m_nt); + if (m_disabledSupplier == null) { + newBackend.m_disabledSupplier = disabledSupplier; + } else { + newBackend.m_disabledSupplier = + () -> m_disabledSupplier.getAsBoolean() || disabledSupplier.getAsBoolean(); + } + return newBackend; + } + @Override public EpilogueBackend getNested(String path) { return m_nestedBackends.computeIfAbsent(path, k -> new NestedBackend(k, this)); @@ -49,6 +73,9 @@ public EpilogueBackend getNested(String path) { @Override public void log(String identifier, int value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((IntegerPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getIntegerTopic(k).publish())) .set(value); @@ -56,6 +83,9 @@ public void log(String identifier, int value) { @Override public void log(String identifier, long value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((IntegerPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getIntegerTopic(k).publish())) .set(value); @@ -63,6 +93,9 @@ public void log(String identifier, long value) { @Override public void log(String identifier, float value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((FloatPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getFloatTopic(k).publish())) .set(value); @@ -70,6 +103,9 @@ public void log(String identifier, float value) { @Override public void log(String identifier, double value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((DoublePublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getDoubleTopic(k).publish())) .set(value); @@ -77,6 +113,9 @@ public void log(String identifier, double value) { @Override public void log(String identifier, boolean value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((BooleanPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getBooleanTopic(k).publish())) .set(value); @@ -84,6 +123,9 @@ public void log(String identifier, boolean value) { @Override public void log(String identifier, byte[] value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((RawPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getRawTopic(k).publish("raw"))) .set(value); @@ -92,6 +134,9 @@ public void log(String identifier, byte[] value) { @Override @SuppressWarnings("PMD.UnnecessaryCastRule") public void log(String identifier, int[] value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } // NT backend only supports int64[], so we have to manually widen to 64 bits before sending long[] widened = new long[value.length]; @@ -106,6 +151,9 @@ public void log(String identifier, int[] value) { @Override public void log(String identifier, long[] value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((IntegerArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getIntegerArrayTopic(k).publish())) .set(value); @@ -113,6 +161,9 @@ public void log(String identifier, long[] value) { @Override public void log(String identifier, float[] value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((FloatArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getFloatArrayTopic(k).publish())) .set(value); @@ -120,6 +171,9 @@ public void log(String identifier, float[] value) { @Override public void log(String identifier, double[] value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((DoubleArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getDoubleArrayTopic(k).publish())) .set(value); @@ -127,6 +181,9 @@ public void log(String identifier, double[] value) { @Override public void log(String identifier, boolean[] value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((BooleanArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getBooleanArrayTopic(k).publish())) .set(value); @@ -134,6 +191,9 @@ public void log(String identifier, boolean[] value) { @Override public void log(String identifier, String value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((StringPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getStringTopic(k).publish())) .set(value); @@ -141,6 +201,9 @@ public void log(String identifier, String value) { @Override public void log(String identifier, String[] value) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } ((StringArrayPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getStringArrayTopic(k).publish())) .set(value); @@ -149,6 +212,9 @@ public void log(String identifier, String[] value) { @Override @SuppressWarnings("unchecked") public void log(String identifier, S value, Struct struct) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } m_nt.addSchema(struct); ((StructPublisher) m_publishers.computeIfAbsent(identifier, k -> m_nt.getStructTopic(k, struct).publish())) @@ -158,6 +224,9 @@ public void log(String identifier, S value, Struct struct) { @Override @SuppressWarnings("unchecked") public void log(String identifier, S[] value, Struct struct) { + if (m_disabledSupplier != null && m_disabledSupplier.getAsBoolean()) { + return; + } m_nt.addSchema(struct); ((StructArrayPublisher) m_publishers.computeIfAbsent(