diff --git a/.vscode/settings.json b/.vscode/settings.json index d08e33e..15dae0d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -20,6 +20,7 @@ ], "java.configuration.updateBuildConfiguration": "automatic", "java.debug.settings.onBuildFailureProceed": true, + "java.dependency.enableDependencyCheckup": false, "java.import.gradle.annotationProcessing.enabled": false, "java.inlayHints.parameterNames.enabled": "literals", "java.inlayHints.parameterNames.exclusions": [ diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json index 9b0f9b7..fb4e6ed 100644 --- a/.wpilib/wpilib_preferences.json +++ b/.wpilib/wpilib_preferences.json @@ -1,6 +1,6 @@ { "enableCppIntellisense": false, "currentLanguage": "java", - "projectYear": "2025", + "projectYear": "2026", "teamNumber": 340 } diff --git a/LICENSE b/LICENSE index 0fcd501..d7f2029 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 Team 340 +Copyright (c) 2023-2026 Team 340 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index c1b854d..388478d 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ A template repository for Java-based robots in the FIRST Robotics Competition. ### Prerequisites -- [WPILib](https://github.com/wpilibsuite/allwpilib/releases) 2025.x +- [WPILib](https://github.com/wpilibsuite/allwpilib/releases) 2026.x - [Node.js](https://nodejs.org/en/download) (v24 LTS Recommended) Node.js is required to support linting via [Spotless](https://github.com/diffplug/spotless), using the [Prettier](https://prettier.io) style guide. You can apply these rules by building, or by running `./gradlew spotlessApply`. Alternatively, if you wish to disable code formatting, you can do so with the following modifications to [build.gradle](build.gradle): @@ -44,7 +44,7 @@ diff --git a/build.gradle b/build.gradle @@ -1,7 +1,6 @@ plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2025.3.2" + id "edu.wpi.first.GradleRIO" version "2026.1.1" - id "com.diffplug.spotless" version "8.1.0" } @@ -65,7 +65,7 @@ diff --git a/build.gradle b/build.gradle - endWithNewline() - removeUnusedImports() - trimTrailingWhitespace() -- prettier(['prettier': '3.7.4', 'prettier-plugin-java': '2.7.7']) +- prettier(['prettier': '3.7.4', 'prettier-plugin-java': '2.8.1']) - .config([ - parser: 'java', - plugins: ['prettier-plugin-java'], diff --git a/WPILib-License.md b/WPILib-License.md index 645e542..eb3061b 100644 --- a/WPILib-License.md +++ b/WPILib-License.md @@ -1,4 +1,4 @@ -Copyright (c) 2009-2024 FIRST and other WPILib contributors +Copyright (c) 2009-2026 FIRST and other WPILib contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/build.gradle b/build.gradle index 62216be..aee2a34 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2025.3.2" + id "edu.wpi.first.GradleRIO" version "2026.1.1" id "com.diffplug.spotless" version "8.1.0" } @@ -60,7 +60,8 @@ deploy { def deployArtifact = deploy.targets.roborio.artifacts.frcJava -// Set to true to use debug for JNI. +// Set to true to use debug for all targets including +// JNI, which will drastically impact performance. wpi.java.debugJni = false // Set this to true to enable desktop support. @@ -103,7 +104,7 @@ spotless { endWithNewline() removeUnusedImports() trimTrailingWhitespace() - prettier(['prettier': '3.7.4', 'prettier-plugin-java': '2.7.7']) + prettier(['prettier': '3.7.4', 'prettier-plugin-java': '2.8.1']) .config([ parser: 'java', plugins: ['prettier-plugin-java'], @@ -131,7 +132,9 @@ wpi.sim.addDriverstation() // knows where to look for our Robot Class. jar { from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } - from sourceSets.main.allSource + from('src') { into 'backup/src' } + from('vendordeps') { into 'backup/vendordeps' } + from('build.gradle') { into 'backup' } manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) duplicatesStrategy = DuplicatesStrategy.INCLUDE } diff --git a/settings.gradle b/settings.gradle index c493958..25f6f6e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,7 +4,7 @@ pluginManagement { repositories { mavenLocal() gradlePluginPortal() - String frcYear = '2025' + String frcYear = '2026' File frcHome if (OperatingSystem.current().isWindows()) { String publicFolder = System.getenv('PUBLIC') diff --git a/src/main/java/org/team340/lib/logging/LoggedRobot.java b/src/main/java/org/team340/lib/logging/LoggedRobot.java index 29b666b..4e4690b 100644 --- a/src/main/java/org/team340/lib/logging/LoggedRobot.java +++ b/src/main/java/org/team340/lib/logging/LoggedRobot.java @@ -3,14 +3,12 @@ import edu.wpi.first.epilogue.logging.EpilogueBackend; import edu.wpi.first.hal.DriverStationJNI; import edu.wpi.first.hal.NotifierJNI; -import edu.wpi.first.networktables.NetworkTableInstance; import edu.wpi.first.wpilibj.DataLogManager; import edu.wpi.first.wpilibj.DriverStation; import edu.wpi.first.wpilibj.IterativeRobotBase; import edu.wpi.first.wpilibj.RobotController; import edu.wpi.first.wpilibj.Threads; import java.util.function.Consumer; -import org.team340.lib.logging.shim.NTEpilogueBackend; import org.team340.lib.tunable.Tunables; import org.team340.lib.tunable.Tunables.Tunable; import org.team340.lib.util.DisableWatchdog; @@ -59,9 +57,6 @@ protected LoggedRobot(double period) { DriverStation.startDataLog(DataLogManager.getLog()); DriverStation.silenceJoystickConnectionWarning(true); - // TODO Remove for 2026 - EpilogueProxy.getConfig().backend = new NTEpilogueBackend(NetworkTableInstance.getDefault()); - EpilogueProxy.getConfig().root = "/Telemetry"; logger = EpilogueProxy.getLogger(this); diff --git a/src/main/java/org/team340/lib/logging/revlib/structs/SparkBaseStruct.java b/src/main/java/org/team340/lib/logging/revlib/structs/SparkBaseStruct.java index e2f89b9..7563cd4 100644 --- a/src/main/java/org/team340/lib/logging/revlib/structs/SparkBaseStruct.java +++ b/src/main/java/org/team340/lib/logging/revlib/structs/SparkBaseStruct.java @@ -1,6 +1,5 @@ package org.team340.lib.logging.revlib.structs; -import com.revrobotics.RelativeEncoder; import com.revrobotics.spark.SparkBase; import edu.wpi.first.util.struct.Struct; import java.nio.ByteBuffer; @@ -9,7 +8,7 @@ public abstract class SparkBaseStruct implements Struct @Override public int getSize() { - return kSizeDouble * 6 + SparkFaultsStruct.struct.getSize() * 2 + SparkWarningsStruct.struct.getSize() * 2; + return kSizeDouble * 7 + SparkFaultsStruct.struct.getSize() * 2 + SparkWarningsStruct.struct.getSize() * 2; } @Override @@ -17,6 +16,7 @@ public String getSchema() { return ( "double appliedOutput; " + "double appliedVoltage; " + + "double closedLoopSetpoint; " + "double motorTemperature; " + "double outputCurrent; " + "double position; " @@ -44,10 +44,12 @@ public T unpack(ByteBuffer bb) { @Override public void pack(ByteBuffer bb, T value) { double appliedOutput = value.getAppliedOutput(); - RelativeEncoder encoder = value.getEncoder(); + var closedLoopController = value.getClosedLoopController(); + var encoder = value.getEncoder(); bb.putDouble(appliedOutput); bb.putDouble(appliedOutput * value.getBusVoltage()); + bb.putDouble(closedLoopController.getSetpoint()); bb.putDouble(value.getMotorTemperature()); bb.putDouble(value.getOutputCurrent()); bb.putDouble(encoder.getPosition()); diff --git a/src/main/java/org/team340/lib/logging/shim/LazyBackend.java b/src/main/java/org/team340/lib/logging/shim/LazyBackend.java deleted file mode 100644 index 70057bb..0000000 --- a/src/main/java/org/team340/lib/logging/shim/LazyBackend.java +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -// Backported from allwpilib@main -// https://github.com/wpilibsuite/allwpilib/tree/632749e6f36f4eed33dc1f5df4a25a544dd2bae1 -// TODO Remove for 2026 - -package org.team340.lib.logging.shim; - -import edu.wpi.first.epilogue.logging.EpilogueBackend; -import edu.wpi.first.util.struct.Struct; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * A backend implementation that only logs data when it changes. Useful for keeping bandwidth and - * file sizes down. However, because it still needs to check that data has changed, it cannot avoid - * expensive sensor reads. - */ -public class LazyBackend implements EpilogueBackend { - - private final EpilogueBackend m_backend; - - // Keep a record of the most recent value written to each entry - // Note that this may duplicate a lot of data, and will box primitives. - private final Map m_previousValues = new HashMap<>(); - private final Map m_subLoggers = new HashMap<>(); - - /** - * Creates a new lazy backend wrapper around another backend. - * - * @param backend the backend to delegate to - */ - public LazyBackend(EpilogueBackend backend) { - this.m_backend = backend; - } - - @Override - public EpilogueBackend lazy() { - // Already lazy, don't need to wrap it again - return this; - } - - @Override - public EpilogueBackend getNested(String path) { - if (!m_subLoggers.containsKey(path)) { - var nested = new NestedBackend(path, this); - m_subLoggers.put(path, nested); - return nested; - } - - return m_subLoggers.get(path); - } - - @Override - public void log(String identifier, int value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof Integer oldValue && oldValue == value) { - // no change - return; - } - - m_previousValues.put(identifier, value); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, long value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof Long oldValue && oldValue == value) { - // no change - return; - } - - m_previousValues.put(identifier, value); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, float value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof Float oldValue && oldValue == value) { - // no change - return; - } - - m_previousValues.put(identifier, value); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, double value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof Double oldValue && oldValue == value) { - // no change - return; - } - - m_previousValues.put(identifier, value); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, boolean value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof Boolean oldValue && oldValue == value) { - // no change - return; - } - - m_previousValues.put(identifier, value); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, byte[] value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof byte[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, int[] value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof int[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, long[] value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof long[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, float[] value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof float[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, double[] value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof double[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, boolean[] value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof boolean[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, String value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof String oldValue && oldValue.equals(value)) { - // no change - return; - } - - m_previousValues.put(identifier, value); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, String[] value) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof String[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value); - } - - @Override - public void log(String identifier, S value, Struct struct) { - var previous = m_previousValues.get(identifier); - - if (Objects.equals(previous, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value); - m_backend.log(identifier, value, struct); - } - - @Override - public void log(String identifier, S[] value, Struct struct) { - var previous = m_previousValues.get(identifier); - - if (previous instanceof Object[] oldValue && Arrays.equals(oldValue, value)) { - // no change - return; - } - - m_previousValues.put(identifier, value.clone()); - m_backend.log(identifier, value, struct); - } -} diff --git a/src/main/java/org/team340/lib/logging/shim/NTEpilogueBackend.java b/src/main/java/org/team340/lib/logging/shim/NTEpilogueBackend.java deleted file mode 100644 index cf8a965..0000000 --- a/src/main/java/org/team340/lib/logging/shim/NTEpilogueBackend.java +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -// Backported from allwpilib@main -// https://github.com/wpilibsuite/allwpilib/tree/632749e6f36f4eed33dc1f5df4a25a544dd2bae1 -// TODO Remove for 2026 - -package org.team340.lib.logging.shim; - -import edu.wpi.first.epilogue.logging.EpilogueBackend; -import edu.wpi.first.networktables.BooleanArrayPublisher; -import edu.wpi.first.networktables.BooleanPublisher; -import edu.wpi.first.networktables.DoubleArrayPublisher; -import edu.wpi.first.networktables.DoublePublisher; -import edu.wpi.first.networktables.FloatArrayPublisher; -import edu.wpi.first.networktables.FloatPublisher; -import edu.wpi.first.networktables.IntegerArrayPublisher; -import edu.wpi.first.networktables.IntegerPublisher; -import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.Publisher; -import edu.wpi.first.networktables.RawPublisher; -import edu.wpi.first.networktables.StringArrayPublisher; -import edu.wpi.first.networktables.StringPublisher; -import edu.wpi.first.networktables.StructArrayPublisher; -import edu.wpi.first.networktables.StructPublisher; -import edu.wpi.first.util.struct.Struct; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; - -/** - * 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 { - - private final NetworkTableInstance m_nt; - - private final Map m_publishers = new HashMap<>(); - private final Map m_nestedBackends = new HashMap<>(); - private final Set> m_seenSchemas = new HashSet<>(); - private final Function m_createIntPublisher; - private final Function m_createFloatPublisher; - private final Function m_createDoublePublisher; - private final Function m_createBooleanPublisher; - private final Function m_createRawPublisher; - private final Function m_createIntegerArrayPublisher; - private final Function m_createFloatArrayPublisher; - private final Function m_createDoubleArrayPublisher; - private final Function m_createBooleanArrayPublisher; - private final Function m_createStringPublisher; - private final Function m_createStringArrayPublisher; - - /** - * Creates a logging backend that sends information to NetworkTables. - * - * @param nt the NetworkTable instance to use to send data to - */ - public NTEpilogueBackend(NetworkTableInstance nt) { - this.m_nt = nt; - m_createIntPublisher = identifier -> m_nt.getIntegerTopic(identifier).publish(); - m_createFloatPublisher = identifier -> m_nt.getFloatTopic(identifier).publish(); - m_createDoublePublisher = identifier -> m_nt.getDoubleTopic(identifier).publish(); - m_createBooleanPublisher = identifier -> m_nt.getBooleanTopic(identifier).publish(); - m_createRawPublisher = identifier -> m_nt.getRawTopic(identifier).publish("raw"); - m_createIntegerArrayPublisher = identifier -> m_nt.getIntegerArrayTopic(identifier).publish(); - m_createFloatArrayPublisher = identifier -> m_nt.getFloatArrayTopic(identifier).publish(); - m_createDoubleArrayPublisher = identifier -> m_nt.getDoubleArrayTopic(identifier).publish(); - m_createBooleanArrayPublisher = identifier -> m_nt.getBooleanArrayTopic(identifier).publish(); - m_createStringPublisher = identifier -> m_nt.getStringTopic(identifier).publish(); - m_createStringArrayPublisher = identifier -> m_nt.getStringArrayTopic(identifier).publish(); - } - - @Override - public EpilogueBackend lazy() { - return new LazyBackend(this); - } - - @Override - public EpilogueBackend getNested(String path) { - if (!m_nestedBackends.containsKey(path)) { - var nested = new NestedBackend(path, this); - m_nestedBackends.put(path, nested); - return nested; - } - - return m_nestedBackends.get(path); - } - - @Override - public void log(String identifier, int value) { - ((IntegerPublisher) m_publishers.computeIfAbsent(identifier, m_createIntPublisher)).set(value); - } - - @Override - public void log(String identifier, long value) { - ((IntegerPublisher) m_publishers.computeIfAbsent(identifier, m_createIntPublisher)).set(value); - } - - @Override - public void log(String identifier, float value) { - ((FloatPublisher) m_publishers.computeIfAbsent(identifier, m_createFloatPublisher)).set(value); - } - - @Override - public void log(String identifier, double value) { - ((DoublePublisher) m_publishers.computeIfAbsent(identifier, m_createDoublePublisher)).set(value); - } - - @Override - public void log(String identifier, boolean value) { - ((BooleanPublisher) m_publishers.computeIfAbsent(identifier, m_createBooleanPublisher)).set(value); - } - - @Override - public void log(String identifier, byte[] value) { - ((RawPublisher) m_publishers.computeIfAbsent(identifier, m_createRawPublisher)).set(value); - } - - @Override - @SuppressWarnings("PMD.UnnecessaryCastRule") - public void log(String identifier, int[] value) { - // NT backend only supports int64[], so we have to manually widen to 64 bits before sending - long[] widened = new long[value.length]; - - for (int i = 0; i < value.length; i++) { - widened[i] = (long) value[i]; - } - - ((IntegerArrayPublisher) m_publishers.computeIfAbsent(identifier, m_createIntegerArrayPublisher)).set(widened); - } - - @Override - public void log(String identifier, long[] value) { - ((IntegerArrayPublisher) m_publishers.computeIfAbsent(identifier, m_createIntegerArrayPublisher)).set(value); - } - - @Override - public void log(String identifier, float[] value) { - ((FloatArrayPublisher) m_publishers.computeIfAbsent(identifier, m_createFloatArrayPublisher)).set(value); - } - - @Override - public void log(String identifier, double[] value) { - ((DoubleArrayPublisher) m_publishers.computeIfAbsent(identifier, m_createDoubleArrayPublisher)).set(value); - } - - @Override - public void log(String identifier, boolean[] value) { - ((BooleanArrayPublisher) m_publishers.computeIfAbsent(identifier, m_createBooleanArrayPublisher)).set(value); - } - - @Override - public void log(String identifier, String value) { - ((StringPublisher) m_publishers.computeIfAbsent(identifier, m_createStringPublisher)).set(value); - } - - @Override - public void log(String identifier, String[] value) { - ((StringArrayPublisher) m_publishers.computeIfAbsent(identifier, m_createStringArrayPublisher)).set(value); - } - - @Override - @SuppressWarnings("unchecked") - public void log(String identifier, S value, Struct struct) { - // NetworkTableInstance.addSchema has checks that we're able to skip, avoiding allocations - if (m_seenSchemas.add(struct)) { - m_nt.addSchema(struct); - } - - if (m_publishers.containsKey(identifier)) { - ((StructPublisher) m_publishers.get(identifier)).set(value); - } else { - StructPublisher publisher = m_nt.getStructTopic(identifier, struct).publish(); - m_publishers.put(identifier, publisher); - publisher.set(value); - } - } - - @Override - @SuppressWarnings("unchecked") - public void log(String identifier, S[] value, Struct struct) { - // NetworkTableInstance.addSchema has checks that we're able to skip, avoiding allocations - if (m_seenSchemas.add(struct)) { - m_nt.addSchema(struct); - } - - if (m_publishers.containsKey(identifier)) { - ((StructArrayPublisher) m_publishers.get(identifier)).set(value); - } else { - StructArrayPublisher publisher = m_nt.getStructArrayTopic(identifier, struct).publish(); - m_publishers.put(identifier, publisher); - publisher.set(value); - } - } -} diff --git a/src/main/java/org/team340/lib/logging/shim/NestedBackend.java b/src/main/java/org/team340/lib/logging/shim/NestedBackend.java deleted file mode 100644 index c261a16..0000000 --- a/src/main/java/org/team340/lib/logging/shim/NestedBackend.java +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -// Backported from allwpilib@main -// https://github.com/wpilibsuite/allwpilib/tree/632749e6f36f4eed33dc1f5df4a25a544dd2bae1 -// TODO Remove for 2026 - -package org.team340.lib.logging.shim; - -import edu.wpi.first.epilogue.logging.EpilogueBackend; -import edu.wpi.first.util.struct.Struct; -import java.util.HashMap; -import java.util.Map; - -/** - * A backend that logs to an underlying backend, prepending all logged data with a specific prefix. - * Useful for logging nested data structures. - */ -public class NestedBackend implements EpilogueBackend { - - private final String m_prefix; - private final EpilogueBackend m_impl; - private final Map m_nestedBackends = new HashMap<>(); - - // String concatenation can be expensive, especially for deeply nested hierarchies with many - // logged fields. For example, logging a hypothetical Robot.elevator.io.getHeight() would result - // in "/Robot/" + "elevator/" + "io/" + "getHeight"; three concatenations and string and byte - // array allocations that need to be cleaned up by the GC. Caching the results means those - // allocations only occur once, resulting in no GC (the strings are always referenced in the - // cache), and minimal time costs (the String object caches its own hash code, so all we do is an - // O(1) table lookup per concatenation) - private final Map m_prefixedIdentifiers = new HashMap<>(); - - /** - * Creates a new nested backed underneath another backend. - * - * @param prefix the prefix to append to all data logged in the nested backend - * @param impl the backend to log to - */ - public NestedBackend(String prefix, EpilogueBackend impl) { - // Add a trailing slash if not already present - if (prefix.endsWith("/")) { - this.m_prefix = prefix; - } else { - this.m_prefix = prefix + "/"; - } - this.m_impl = impl; - } - - @Override - public EpilogueBackend lazy() { - return new LazyBackend(this); - } - - /** - * Fast lookup to avoid redundant `m_prefix + identifier` concatenations. If the identifier has - * not been seen before, we compute the concatenation and cache the result for later invocations - * to read. This avoids redundantly recomputing the same concatenations every loop and - * significantly cuts down on the CPU and memory overhead of the Epilogue library. - * - * @param identifier The identifier to prepend with {@link #m_prefix}. - * @return The concatenated string. - */ - private String withPrefix(String identifier) { - // Using computeIfAbsent would result in a new lambda object allocation on every call - if (m_prefixedIdentifiers.containsKey(identifier)) { - return m_prefixedIdentifiers.get(identifier); - } - - String result = m_prefix + identifier; - m_prefixedIdentifiers.put(identifier, result); - return result; - } - - @Override - public EpilogueBackend getNested(String path) { - if (!m_nestedBackends.containsKey(path)) { - var nested = new NestedBackend(path, this); - m_nestedBackends.put(path, nested); - return nested; - } - - return m_nestedBackends.get(path); - } - - @Override - public void log(String identifier, int value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, long value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, float value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, double value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, boolean value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, byte[] value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, int[] value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, long[] value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, float[] value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, double[] value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, boolean[] value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, String value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, String[] value) { - m_impl.log(withPrefix(identifier), value); - } - - @Override - public void log(String identifier, S value, Struct struct) { - m_impl.log(withPrefix(identifier), value, struct); - } - - @Override - public void log(String identifier, S[] value, Struct struct) { - m_impl.log(withPrefix(identifier), value, struct); - } -} diff --git a/src/main/java/org/team340/lib/logging/wpimath/ExponentialProfileStateLogger.java b/src/main/java/org/team340/lib/logging/wpimath/ExponentialProfileStateLogger.java deleted file mode 100644 index 9c361c3..0000000 --- a/src/main/java/org/team340/lib/logging/wpimath/ExponentialProfileStateLogger.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.team340.lib.logging.wpimath; - -import edu.wpi.first.epilogue.CustomLoggerFor; -import edu.wpi.first.epilogue.logging.ClassSpecificLogger; -import edu.wpi.first.epilogue.logging.EpilogueBackend; -import edu.wpi.first.math.trajectory.ExponentialProfile; - -@CustomLoggerFor(ExponentialProfile.State.class) -public class ExponentialProfileStateLogger extends ClassSpecificLogger { - - public ExponentialProfileStateLogger() { - super(ExponentialProfile.State.class); - } - - @Override - public void update(EpilogueBackend backend, ExponentialProfile.State state) { - backend.log("position", state.position); - backend.log("velocity", state.velocity); - } -} diff --git a/src/main/java/org/team340/lib/logging/wpimath/TrapezoidProfileStateLogger.java b/src/main/java/org/team340/lib/logging/wpimath/TrapezoidProfileStateLogger.java deleted file mode 100644 index 309900c..0000000 --- a/src/main/java/org/team340/lib/logging/wpimath/TrapezoidProfileStateLogger.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.team340.lib.logging.wpimath; - -import edu.wpi.first.epilogue.CustomLoggerFor; -import edu.wpi.first.epilogue.logging.ClassSpecificLogger; -import edu.wpi.first.epilogue.logging.EpilogueBackend; -import edu.wpi.first.math.trajectory.TrapezoidProfile; - -@CustomLoggerFor(TrapezoidProfile.State.class) -public class TrapezoidProfileStateLogger extends ClassSpecificLogger { - - public TrapezoidProfileStateLogger() { - super(TrapezoidProfile.State.class); - } - - @Override - public void update(EpilogueBackend backend, TrapezoidProfile.State state) { - backend.log("position", state.position); - backend.log("velocity", state.velocity); - } -} diff --git a/src/main/java/org/team340/lib/math/Math2.java b/src/main/java/org/team340/lib/math/Math2.java index c025b10..df68719 100644 --- a/src/main/java/org/team340/lib/math/Math2.java +++ b/src/main/java/org/team340/lib/math/Math2.java @@ -46,9 +46,10 @@ public static ChassisSpeeds discretizeChassisSpeeds(ChassisSpeeds speeds, double double dtheta = speeds.omegaRadiansPerSecond * dtSeconds; double sin = -dtheta / 2.0; - double cos = Math.abs(Math.cos(dtheta) - 1.0) < 1e-6 - ? 1.0 - ((1.0 / 12.0) * dtheta * dtheta) - : (sin * Math.sin(dtheta)) / (Math.cos(dtheta) - 1.0); + double cos = + Math.abs(Math.cos(dtheta) - 1.0) < 1e-6 + ? 1.0 - ((1.0 / 12.0) * dtheta * dtheta) + : (sin * Math.sin(dtheta)) / (Math.cos(dtheta) - 1.0); double dt = dtSeconds; double dx = speeds.vxMetersPerSecond * dt; diff --git a/src/main/java/org/team340/lib/math/PAPFController.java b/src/main/java/org/team340/lib/math/PAPFController.java index 29d89a4..b616aab 100644 --- a/src/main/java/org/team340/lib/math/PAPFController.java +++ b/src/main/java/org/team340/lib/math/PAPFController.java @@ -270,12 +270,10 @@ public ChassisSpeeds repulsorDrive(ChassisSpeeds input, Pose2d currentPose) { obstacle.applyForce(currentPose.getX(), currentPose.getY(), sample); } - double repulsion_x = sample.x * input.vxMetersPerSecond < 0.0 - ? sample.x * Math.abs(input.vxMetersPerSecond) - : 0.0; - double repulsion_y = sample.y * input.vyMetersPerSecond < 0.0 - ? sample.y * Math.abs(input.vyMetersPerSecond) - : 0.0; + double repulsion_x = + sample.x * input.vxMetersPerSecond < 0.0 ? sample.x * Math.abs(input.vxMetersPerSecond) : 0.0; + double repulsion_y = + sample.y * input.vyMetersPerSecond < 0.0 ? sample.y * Math.abs(input.vyMetersPerSecond) : 0.0; return new ChassisSpeeds( input.vxMetersPerSecond + repulsion_x, diff --git a/src/main/java/org/team340/lib/math/geometry/VisionMeasurement.java b/src/main/java/org/team340/lib/math/geometry/VisionMeasurement.java index 1b1b055..618359a 100644 --- a/src/main/java/org/team340/lib/math/geometry/VisionMeasurement.java +++ b/src/main/java/org/team340/lib/math/geometry/VisionMeasurement.java @@ -9,8 +9,11 @@ * Represents a measurement from vision to apply to a pose estimator. * @see {@link PoseEstimator#addVisionMeasurement(Pose2d, double, Matrix)}. */ -public final record VisionMeasurement(Pose2d pose, double timestamp, Matrix stdDevs) implements - Comparable { +public final record VisionMeasurement( + Pose2d pose, + double timestamp, + Matrix stdDevs +) implements Comparable { /** * Represents a measurement from vision to apply to a pose estimator. * @see {@link PoseEstimator#addVisionMeasurement(Pose2d, double)}. diff --git a/src/main/java/org/team340/lib/swerve/SwerveAPI.java b/src/main/java/org/team340/lib/swerve/SwerveAPI.java index d012ff0..0167cac 100644 --- a/src/main/java/org/team340/lib/swerve/SwerveAPI.java +++ b/src/main/java/org/team340/lib/swerve/SwerveAPI.java @@ -209,10 +209,6 @@ public void tareRotation(Perspective perspective) { odometryMutex.lock(); try { - // Patch for an upstream bug. - // TODO Fixed by https://github.com/wpilibsuite/allwpilib/pull/8285 - odometry.resetPose(state.pose); - poseEstimator.resetRotation(rotation); state.pose = poseEstimator.getEstimatedPosition(); odometryThread.poseHistory.clear(); @@ -351,9 +347,10 @@ public void applySpeeds(ChassisSpeeds speeds, Perspective perspective, boolean d if (ratelimit) { double now = Timer.getFPGATimestamp(); - ChassisSpeeds lastSpeeds = now - lastRatelimit < config.period * 4.0 - ? perspective.toPerspectiveSpeeds(state.targetSpeeds, lastRobotAngle) - : perspective.toPerspectiveSpeeds(state.speeds, state.rotation); + ChassisSpeeds lastSpeeds = + now - lastRatelimit < config.period * 4.0 + ? perspective.toPerspectiveSpeeds(state.targetSpeeds, lastRobotAngle) + : perspective.toPerspectiveSpeeds(state.speeds, state.rotation); double vx_l = lastSpeeds.vxMetersPerSecond; double vy_l = lastSpeeds.vyMetersPerSecond; @@ -437,7 +434,7 @@ public void applyStop(boolean lock) { * Drives the robot using open-loop voltage. Intended for characterization. * Plumbing for recording device voltage via their Java API is intentionally * unavailable, as GC pressure and CAN latency will result in inaccurate data. - * Use Phoenix Signal Logging or URCL instead. + * Use Phoenix Signal Logging or REV's StatusLogger instead. * @param voltage The voltage to apply to the move motors. * @param angle The robot-relative angle to apply to the turn motors. */ diff --git a/src/main/java/org/team340/lib/swerve/hardware/SwerveEncoders.java b/src/main/java/org/team340/lib/swerve/hardware/SwerveEncoders.java index c742885..bcc5dbf 100644 --- a/src/main/java/org/team340/lib/swerve/hardware/SwerveEncoders.java +++ b/src/main/java/org/team340/lib/swerve/hardware/SwerveEncoders.java @@ -12,10 +12,10 @@ import com.reduxrobotics.canand.CanandEventLoop; import com.reduxrobotics.sensors.canandmag.Canandmag; import com.reduxrobotics.sensors.canandmag.CanandmagSettings; +import com.revrobotics.spark.FeedbackSensor; import com.revrobotics.spark.SparkAbsoluteEncoder; import com.revrobotics.spark.SparkFlex; import com.revrobotics.spark.SparkMax; -import com.revrobotics.spark.config.ClosedLoopConfig.FeedbackSensor; import com.revrobotics.spark.config.SparkFlexConfig; import com.revrobotics.spark.config.SparkMaxConfig; import edu.wpi.first.units.measure.Angle; diff --git a/src/main/java/org/team340/lib/swerve/hardware/SwerveMotors.java b/src/main/java/org/team340/lib/swerve/hardware/SwerveMotors.java index 7316689..85a6e83 100644 --- a/src/main/java/org/team340/lib/swerve/hardware/SwerveMotors.java +++ b/src/main/java/org/team340/lib/swerve/hardware/SwerveMotors.java @@ -11,14 +11,12 @@ import com.ctre.phoenix6.signals.NeutralModeValue; import com.revrobotics.REVLibError; import com.revrobotics.RelativeEncoder; -import com.revrobotics.spark.ClosedLoopSlot; +import com.revrobotics.spark.FeedbackSensor; import com.revrobotics.spark.SparkBase.ControlType; import com.revrobotics.spark.SparkClosedLoopController; -import com.revrobotics.spark.SparkClosedLoopController.ArbFFUnits; import com.revrobotics.spark.SparkFlex; import com.revrobotics.spark.SparkLowLevel.MotorType; import com.revrobotics.spark.SparkMax; -import com.revrobotics.spark.config.ClosedLoopConfig.FeedbackSensor; import com.revrobotics.spark.config.SparkBaseConfig.IdleMode; import com.revrobotics.spark.config.SparkFlexConfig; import com.revrobotics.spark.config.SparkMaxConfig; @@ -118,7 +116,6 @@ public static SwerveMotor.Ctor sparkMax(int id, boolean inverted) { SparkMax sparkMax = new SparkMax(id, MotorType.kBrushless); RelativeEncoder relativeEncoder = sparkMax.getEncoder(); SparkClosedLoopController pid = sparkMax.getClosedLoopController(); - ClosedLoopSlot pidSlot = ClosedLoopSlot.kSlot0; double[] pidGains = isMoveMotor ? config.movePID : config.turnPID; double[] ffGains = isMoveMotor ? config.moveFF : new double[] { 0.0, 0.0 }; @@ -135,7 +132,9 @@ public static SwerveMotor.Ctor sparkMax(int id, boolean inverted) { sparkConfig.closedLoop .feedbackSensor(FeedbackSensor.kPrimaryEncoder) - .pid(pidGains[0], pidGains[1], pidGains[2], pidSlot); + .pid(pidGains[0], pidGains[1], pidGains[2]) + .feedForward.kS(ffGains[0]) + .kV(ffGains[1]); sparkConfig.encoder .positionConversionFactor(1.0) @@ -165,7 +164,7 @@ public double getPosition() { @Override public void setPosition(double position) { - pid.setReference(position, ControlType.kPosition, pidSlot, 0.0, ArbFFUnits.kVoltage); + pid.setSetpoint(position, ControlType.kPosition); } @Override @@ -175,13 +174,7 @@ public double getVelocity() { @Override public void setVelocity(double velocity) { - pid.setReference( - velocity, - ControlType.kVelocity, - pidSlot, - ffGains[0] * Math.signum(velocity) + ffGains[1] * velocity, - ArbFFUnits.kVoltage - ); + pid.setSetpoint(velocity, ControlType.kVelocity); } @Override @@ -191,15 +184,14 @@ public void setVoltage(double voltage) { @Override public void reapplyGains() { - if (isMoveMotor) { - ffGains[0] = config.moveFF[0]; - ffGains[1] = config.moveFF[1]; - } - double[] pidGains = isMoveMotor ? config.movePID : config.turnPID; + double[] ffGains = isMoveMotor ? config.moveFF : new double[] { 0.0, 0.0 }; var newConfig = new SparkMaxConfig(); - newConfig.closedLoop.pid(pidGains[0], pidGains[1], pidGains[2], pidSlot); + newConfig.closedLoop + .pid(pidGains[0], pidGains[1], pidGains[2]) + .feedForward.kS(ffGains[0]) + .kV(ffGains[1]); RevUtil.configEphemeral(sparkMax, newConfig); } @@ -244,7 +236,6 @@ public static SwerveMotor.Ctor sparkFlex(int id, boolean inverted) { SparkFlex sparkFlex = new SparkFlex(id, MotorType.kBrushless); RelativeEncoder relativeEncoder = sparkFlex.getEncoder(); SparkClosedLoopController pid = sparkFlex.getClosedLoopController(); - ClosedLoopSlot pidSlot = ClosedLoopSlot.kSlot0; double[] pidGains = isMoveMotor ? config.movePID : config.turnPID; double[] ffGains = isMoveMotor ? config.moveFF : new double[] { 0.0, 0.0 }; @@ -261,7 +252,9 @@ public static SwerveMotor.Ctor sparkFlex(int id, boolean inverted) { sparkConfig.closedLoop .feedbackSensor(FeedbackSensor.kPrimaryEncoder) - .pid(pidGains[0], pidGains[1], pidGains[2], pidSlot); + .pid(pidGains[0], pidGains[1], pidGains[2]) + .feedForward.kS(ffGains[0]) + .kV(ffGains[1]); sparkConfig.encoder .positionConversionFactor(1.0) @@ -291,7 +284,7 @@ public double getPosition() { @Override public void setPosition(double position) { - pid.setReference(position, ControlType.kPosition, pidSlot, 0.0, ArbFFUnits.kVoltage); + pid.setSetpoint(position, ControlType.kPosition); } @Override @@ -301,13 +294,7 @@ public double getVelocity() { @Override public void setVelocity(double velocity) { - pid.setReference( - velocity, - ControlType.kVelocity, - pidSlot, - ffGains[0] * Math.signum(velocity) + ffGains[1] * velocity, - ArbFFUnits.kVoltage - ); + pid.setSetpoint(velocity, ControlType.kVelocity); } @Override @@ -317,15 +304,14 @@ public void setVoltage(double voltage) { @Override public void reapplyGains() { - if (isMoveMotor) { - ffGains[0] = config.moveFF[0]; - ffGains[1] = config.moveFF[1]; - } - double[] pidGains = isMoveMotor ? config.movePID : config.turnPID; + double[] ffGains = isMoveMotor ? config.moveFF : new double[] { 0.0, 0.0 }; var newConfig = new SparkFlexConfig(); - newConfig.closedLoop.pid(pidGains[0], pidGains[1], pidGains[2], pidSlot); + newConfig.closedLoop + .pid(pidGains[0], pidGains[1], pidGains[2]) + .feedForward.kS(ffGains[0]) + .kV(ffGains[1]); RevUtil.configEphemeral(sparkFlex, newConfig); } diff --git a/src/main/java/org/team340/lib/tunable/ThirdParty.java b/src/main/java/org/team340/lib/tunable/ThirdParty.java index cae1515..f131e10 100644 --- a/src/main/java/org/team340/lib/tunable/ThirdParty.java +++ b/src/main/java/org/team340/lib/tunable/ThirdParty.java @@ -78,6 +78,7 @@ private static void profiledPIDController() { private static void sparkMax() { Tunables.registerHandler(SparkMax.class, (table, spark) -> { var pidConfig = spark.configAccessor.closedLoop; + var ffConfig = pidConfig.feedForward; var slot = ClosedLoopSlot.kSlot0; table.value("kP", pidConfig.getP(slot), v -> { @@ -95,9 +96,29 @@ private static void sparkMax() { newConfig.closedLoop.d(v, slot); RevUtil.configEphemeral(spark, newConfig); }); - table.value("kV", pidConfig.getFF(slot), v -> { + table.value("kS", ffConfig.getkS(slot), v -> { var newConfig = new SparkMaxConfig(); - newConfig.closedLoop.velocityFF(v, slot); + newConfig.closedLoop.feedForward.kS(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kV", ffConfig.getkV(slot), v -> { + var newConfig = new SparkMaxConfig(); + newConfig.closedLoop.feedForward.kV(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kA", ffConfig.getkA(slot), v -> { + var newConfig = new SparkMaxConfig(); + newConfig.closedLoop.feedForward.kA(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kG", ffConfig.getkG(slot), v -> { + var newConfig = new SparkMaxConfig(); + newConfig.closedLoop.feedForward.kG(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kCos", ffConfig.getkCos(slot), v -> { + var newConfig = new SparkMaxConfig(); + newConfig.closedLoop.feedForward.kCos(v, slot); RevUtil.configEphemeral(spark, newConfig); }); table.value("iZone", pidConfig.getIZone(slot), v -> { @@ -124,9 +145,9 @@ private static void sparkMax() { var motionConfig = spark.configAccessor.closedLoop.maxMotion; TunableTable motionTable = table.getNested("motion"); - motionTable.value("velocity", motionConfig.getMaxVelocity(slot), v -> { + motionTable.value("velocity", motionConfig.getCruiseVelocity(slot), v -> { var newConfig = new SparkMaxConfig(); - newConfig.closedLoop.maxMotion.maxVelocity(v, slot); + newConfig.closedLoop.maxMotion.cruiseVelocity(v, slot); RevUtil.configEphemeral(spark, newConfig); }); motionTable.value("acceleration", motionConfig.getMaxAcceleration(slot), v -> { @@ -134,9 +155,9 @@ private static void sparkMax() { newConfig.closedLoop.maxMotion.maxAcceleration(v, slot); RevUtil.configEphemeral(spark, newConfig); }); - motionTable.value("allowedClosedLoopError", motionConfig.getAllowedClosedLoopError(slot), v -> { + motionTable.value("allowedProfileError", motionConfig.getAllowedProfileError(slot), v -> { var newConfig = new SparkMaxConfig(); - newConfig.closedLoop.maxMotion.allowedClosedLoopError(v, slot); + newConfig.closedLoop.maxMotion.allowedProfileError(v, slot); RevUtil.configEphemeral(spark, newConfig); }); }); @@ -146,6 +167,7 @@ private static void sparkMax() { private static void sparkFlex() { Tunables.registerHandler(SparkFlex.class, (table, spark) -> { var pidConfig = spark.configAccessor.closedLoop; + var ffConfig = pidConfig.feedForward; var slot = ClosedLoopSlot.kSlot0; table.value("kP", pidConfig.getP(slot), v -> { @@ -163,9 +185,29 @@ private static void sparkFlex() { newConfig.closedLoop.d(v, slot); RevUtil.configEphemeral(spark, newConfig); }); - table.value("kV", pidConfig.getFF(slot), v -> { + table.value("kS", ffConfig.getkS(slot), v -> { + var newConfig = new SparkFlexConfig(); + newConfig.closedLoop.feedForward.kS(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kV", ffConfig.getkV(slot), v -> { + var newConfig = new SparkFlexConfig(); + newConfig.closedLoop.feedForward.kV(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kA", ffConfig.getkA(slot), v -> { + var newConfig = new SparkFlexConfig(); + newConfig.closedLoop.feedForward.kA(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kG", ffConfig.getkG(slot), v -> { + var newConfig = new SparkFlexConfig(); + newConfig.closedLoop.feedForward.kG(v, slot); + RevUtil.configEphemeral(spark, newConfig); + }); + table.value("kCos", ffConfig.getkCos(slot), v -> { var newConfig = new SparkFlexConfig(); - newConfig.closedLoop.velocityFF(v, slot); + newConfig.closedLoop.feedForward.kCos(v, slot); RevUtil.configEphemeral(spark, newConfig); }); table.value("iZone", pidConfig.getIZone(slot), v -> { @@ -192,9 +234,9 @@ private static void sparkFlex() { var motionConfig = spark.configAccessor.closedLoop.maxMotion; TunableTable motionTable = table.getNested("motion"); - motionTable.value("velocity", motionConfig.getMaxVelocity(slot), v -> { + motionTable.value("velocity", motionConfig.getCruiseVelocity(slot), v -> { var newConfig = new SparkFlexConfig(); - newConfig.closedLoop.maxMotion.maxVelocity(v, slot); + newConfig.closedLoop.maxMotion.cruiseVelocity(v, slot); RevUtil.configEphemeral(spark, newConfig); }); motionTable.value("acceleration", motionConfig.getMaxAcceleration(slot), v -> { @@ -202,9 +244,9 @@ private static void sparkFlex() { newConfig.closedLoop.maxMotion.maxAcceleration(v, slot); RevUtil.configEphemeral(spark, newConfig); }); - motionTable.value("allowedClosedLoopError", motionConfig.getAllowedClosedLoopError(slot), v -> { + motionTable.value("allowedProfileError", motionConfig.getAllowedProfileError(slot), v -> { var newConfig = new SparkFlexConfig(); - newConfig.closedLoop.maxMotion.allowedClosedLoopError(v, slot); + newConfig.closedLoop.maxMotion.allowedProfileError(v, slot); RevUtil.configEphemeral(spark, newConfig); }); }); diff --git a/src/main/java/org/team340/lib/util/command/AutoChooser.java b/src/main/java/org/team340/lib/util/command/AutoChooser.java index 6482a97..35fee89 100644 --- a/src/main/java/org/team340/lib/util/command/AutoChooser.java +++ b/src/main/java/org/team340/lib/util/command/AutoChooser.java @@ -143,7 +143,7 @@ private void update() { boolean schedule = DriverStation.isAutonomousEnabled() && enableScheduling; if (!running && schedule) { - activeCommand.schedule(); + CommandScheduler.getInstance().schedule(activeCommand); running = true; } else if (running && !schedule) { activeCommand.cancel(); diff --git a/vendordeps/Phoenix6-frc2025-latest.json b/vendordeps/Phoenix6-frc2026-latest.json similarity index 85% rename from vendordeps/Phoenix6-frc2025-latest.json rename to vendordeps/Phoenix6-frc2026-latest.json index 6f40c84..8f6e30f 100644 --- a/vendordeps/Phoenix6-frc2025-latest.json +++ b/vendordeps/Phoenix6-frc2026-latest.json @@ -1,32 +1,32 @@ { - "fileName": "Phoenix6-frc2025-latest.json", + "fileName": "Phoenix6-frc2026-latest.json", "name": "CTRE-Phoenix (v6)", - "version": "25.4.0", - "frcYear": "2025", + "version": "26.1.0", + "frcYear": "2026", "uuid": "e995de00-2c64-4df5-8831-c1441420ff19", "mavenUrls": [ "https://maven.ctr-electronics.com/release/" ], - "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2025-latest.json", + "jsonUrl": "https://maven.ctr-electronics.com/release/com/ctre/phoenix6/latest/Phoenix6-frc2026-latest.json", "conflictsWith": [ { "uuid": "e7900d8d-826f-4dca-a1ff-182f658e98af", "errorMessage": "Users can not have both the replay and regular Phoenix 6 vendordeps in their robot program.", - "offlineFileName": "Phoenix6-replay-frc2025-latest.json" + "offlineFileName": "Phoenix6-replay-frc2026-latest.json" } ], "javaDependencies": [ { "groupId": "com.ctre.phoenix6", "artifactId": "wpiapi-java", - "version": "25.4.0" + "version": "26.1.0" } ], "jniDependencies": [ { "groupId": "com.ctre.phoenix6", "artifactId": "api-cpp", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -40,7 +40,7 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "tools", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -54,7 +54,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "api-cpp-sim", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -68,7 +68,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "tools-sim", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -82,7 +82,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simTalonSRX", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -96,7 +96,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simVictorSPX", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -110,21 +110,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simPigeonIMU", - "version": "25.4.0", - "isJar": false, - "skipInvalidPlatforms": true, - "validPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simCANCoder", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -138,7 +124,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFX", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -152,7 +138,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFXS", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -166,7 +152,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANcoder", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -180,7 +166,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProPigeon2", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -194,7 +180,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANrange", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -208,7 +194,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdi", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -222,7 +208,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdle", - "version": "25.4.0", + "version": "26.1.0", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ @@ -238,7 +224,7 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "wpiapi-cpp", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_Phoenix6_WPI", "headerClassifier": "headers", "sharedLibrary": true, @@ -254,7 +240,7 @@ { "groupId": "com.ctre.phoenix6", "artifactId": "tools", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_PhoenixTools", "headerClassifier": "headers", "sharedLibrary": true, @@ -270,7 +256,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "wpiapi-cpp-sim", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_Phoenix6_WPISim", "headerClassifier": "headers", "sharedLibrary": true, @@ -286,7 +272,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "tools-sim", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_PhoenixTools_Sim", "headerClassifier": "headers", "sharedLibrary": true, @@ -302,7 +288,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simTalonSRX", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimTalonSRX", "headerClassifier": "headers", "sharedLibrary": true, @@ -318,7 +304,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simVictorSPX", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimVictorSPX", "headerClassifier": "headers", "sharedLibrary": true, @@ -334,7 +320,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simPigeonIMU", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimPigeonIMU", "headerClassifier": "headers", "sharedLibrary": true, @@ -347,26 +333,10 @@ ], "simMode": "swsim" }, - { - "groupId": "com.ctre.phoenix6.sim", - "artifactId": "simCANCoder", - "version": "25.4.0", - "libName": "CTRE_SimCANCoder", - "headerClassifier": "headers", - "sharedLibrary": true, - "skipInvalidPlatforms": true, - "binaryPlatforms": [ - "windowsx86-64", - "linuxx86-64", - "linuxarm64", - "osxuniversal" - ], - "simMode": "swsim" - }, { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFX", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimProTalonFX", "headerClassifier": "headers", "sharedLibrary": true, @@ -382,7 +352,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProTalonFXS", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimProTalonFXS", "headerClassifier": "headers", "sharedLibrary": true, @@ -398,7 +368,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANcoder", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimProCANcoder", "headerClassifier": "headers", "sharedLibrary": true, @@ -414,7 +384,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProPigeon2", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimProPigeon2", "headerClassifier": "headers", "sharedLibrary": true, @@ -430,7 +400,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANrange", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimProCANrange", "headerClassifier": "headers", "sharedLibrary": true, @@ -446,7 +416,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdi", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimProCANdi", "headerClassifier": "headers", "sharedLibrary": true, @@ -462,7 +432,7 @@ { "groupId": "com.ctre.phoenix6.sim", "artifactId": "simProCANdle", - "version": "25.4.0", + "version": "26.1.0", "libName": "CTRE_SimProCANdle", "headerClassifier": "headers", "sharedLibrary": true, diff --git a/vendordeps/REVLib.json b/vendordeps/REVLib.json index ac62be8..7664dd7 100644 --- a/vendordeps/REVLib.json +++ b/vendordeps/REVLib.json @@ -1,25 +1,55 @@ { "fileName": "REVLib.json", "name": "REVLib", - "version": "2025.0.3", - "frcYear": "2025", + "version": "2026.0.0-beta-1", + "frcYear": "2026", "uuid": "3f48eb8c-50fe-43a6-9cb7-44c86353c4cb", "mavenUrls": [ "https://maven.revrobotics.com/" ], - "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2025.json", + "jsonUrl": "https://software-metadata.revrobotics.com/REVLib-2026.json", "javaDependencies": [ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-java", - "version": "2025.0.3" + "version": "2026.0.0-beta-1" } ], "jniDependencies": [ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-driver", - "version": "2025.0.3", + "version": "2026.0.0-beta-1", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibBackendDriver", + "version": "2026.0.0-beta-1", + "skipInvalidPlatforms": true, + "isJar": false, + "validPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibWpiBackendDriver", + "version": "2026.0.0-beta-1", "skipInvalidPlatforms": true, "isJar": false, "validPlatforms": [ @@ -36,7 +66,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-cpp", - "version": "2025.0.3", + "version": "2026.0.0-beta-1", "libName": "REVLib", "headerClassifier": "headers", "sharedLibrary": false, @@ -53,7 +83,7 @@ { "groupId": "com.revrobotics.frc", "artifactId": "REVLib-driver", - "version": "2025.0.3", + "version": "2026.0.0-beta-1", "libName": "REVLibDriver", "headerClassifier": "headers", "sharedLibrary": false, @@ -66,6 +96,38 @@ "linuxarm32", "osxuniversal" ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibBackendDriver", + "version": "2026.0.0-beta-1", + "libName": "BackendDriver", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] + }, + { + "groupId": "com.revrobotics.frc", + "artifactId": "RevLibWpiBackendDriver", + "version": "2026.0.0-beta-1", + "libName": "REVLibWpi", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "windowsx86-64", + "linuxarm64", + "linuxx86-64", + "linuxathena", + "linuxarm32", + "osxuniversal" + ] } ] } \ No newline at end of file diff --git a/vendordeps/ReduxLib-2025.0.1.json b/vendordeps/ReduxLib-2026.0.0-beta1.json similarity index 75% rename from vendordeps/ReduxLib-2025.0.1.json rename to vendordeps/ReduxLib-2026.0.0-beta1.json index 6cc750e..8195bad 100644 --- a/vendordeps/ReduxLib-2025.0.1.json +++ b/vendordeps/ReduxLib-2026.0.0-beta1.json @@ -1,31 +1,30 @@ { - "fileName": "ReduxLib-2025.0.1.json", + "fileName": "ReduxLib-2026.0.0-beta1.json", "name": "ReduxLib", - "version": "2025.0.1", - "frcYear": "2025", + "version": "2026.0.0-beta1", + "frcYear": "2026", "uuid": "151ecca8-670b-4026-8160-cdd2679ef2bd", "mavenUrls": [ "https://maven.reduxrobotics.com/" ], - "jsonUrl": "https://frcsdk.reduxrobotics.com/ReduxLib_2025.json", + "jsonUrl": "https://frcsdk.reduxrobotics.com/ReduxLib_2026.json", "javaDependencies": [ { "groupId": "com.reduxrobotics.frc", "artifactId": "ReduxLib-java", - "version": "2025.0.1" + "version": "2026.0.0-beta1" } ], "jniDependencies": [ { "groupId": "com.reduxrobotics.frc", - "artifactId": "ReduxLib-driver", - "version": "2025.0.1", + "artifactId": "ReduxLib-fifo", + "version": "2026.0.0-beta1", "isJar": false, "skipInvalidPlatforms": true, "validPlatforms": [ "linuxathena", "linuxx86-64", - "linuxarm32", "linuxarm64", "osxuniversal", "windowsx86-64" @@ -36,7 +35,7 @@ { "groupId": "com.reduxrobotics.frc", "artifactId": "ReduxLib-cpp", - "version": "2025.0.1", + "version": "2026.0.0-beta1", "libName": "ReduxLib", "headerClassifier": "headers", "sourcesClassifier": "sources", @@ -45,7 +44,6 @@ "binaryPlatforms": [ "linuxathena", "linuxx86-64", - "linuxarm32", "linuxarm64", "osxuniversal", "windowsx86-64" @@ -53,16 +51,15 @@ }, { "groupId": "com.reduxrobotics.frc", - "artifactId": "ReduxLib-driver", - "version": "2025.0.1", - "libName": "ReduxCore", + "artifactId": "ReduxLib-fifo", + "version": "2026.0.0-beta1", + "libName": "reduxfifo", "headerClassifier": "headers", "sharedLibrary": true, "skipInvalidPlatforms": true, "binaryPlatforms": [ "linuxathena", "linuxx86-64", - "linuxarm32", "linuxarm64", "osxuniversal", "windowsx86-64" diff --git a/vendordeps/WPILibNewCommands.json b/vendordeps/WPILibNewCommands.json index 3718e0a..d90630e 100644 --- a/vendordeps/WPILibNewCommands.json +++ b/vendordeps/WPILibNewCommands.json @@ -3,7 +3,7 @@ "name": "WPILib-New-Commands", "version": "1.0.0", "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", - "frcYear": "2025", + "frcYear": "2026", "mavenUrls": [], "jsonUrl": "", "javaDependencies": [ @@ -25,6 +25,7 @@ "sharedLibrary": true, "skipInvalidPlatforms": true, "binaryPlatforms": [ + "linuxsystemcore", "linuxathena", "linuxarm32", "linuxarm64",