diff --git a/controls/build.gradle b/controls/build.gradle index 6415c0b..6580b72 100644 --- a/controls/build.gradle +++ b/controls/build.gradle @@ -1,19 +1,96 @@ +import java.text.SimpleDateFormat import com.vanniktech.maven.publish.SonatypeHost import com.vanniktech.maven.publish.JavaLibrary import com.vanniktech.maven.publish.JavadocJar plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' + id "java" + id "maven-publish" + id "com.peterabeles.gversion" version "1.10" id "com.diffplug.spotless" version "6.24.0" id "com.vanniktech.maven.publish" version "0.30.0" } +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +// Set this to true to enable desktop support. +def includeDesktopSupport = true + +configurations.all { + // exclude group: "edu.wpi.first.wpilibj" +} + +task(checkAkitInstall, dependsOn: "classes", type: JavaExec) { + mainClass = "org.littletonrobotics.junction.CheckInstall" + classpath = sourceSets.main.runtimeClasspath +} +// TODO: Figure out why advantagekit won't let us build the project +//compileJava.finalizedBy checkAkitInstall + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. +dependencies { + + //def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text) + //annotationProcessor "org.littletonrobotics.akit.junction:junction-autolog:$akitJson.version" + def akitVersion = "4.0.0-alpha-1" + annotationProcessor "org.littletonrobotics.akit.junction:junction-autolog:$akitVersion" + + implementation "org.littletonrobotics.akit.junction:junction-core:$akitVersion" + + def photonVersion = "v2025.0.0-beta-5" + implementation "org.photonvision:photonlib-java:$photonVersion" + implementation "org.photonvision:photontargeting-java:$photonVersion" + + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + implementation 'com.googlecode.json-simple:json-simple:1.1.1' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' +} + +// Configure string concat to always inline compile +tasks.withType(JavaCompile) { + options.compilerArgs.add '-XDstringConcat=inline' +} + +// project.compileJava.dependsOn(createVersionFile) +// gversion { +// srcDir = "src/main/java/" +// classPackage = "frc.robot" +// className = "BuildConstants" +// dateFormat = "yyyy-MM-dd HH:mm:ss z" +// timeZone = "America/New_York" +// indent = " " +// } + repositories { - // Use Maven Central for resolving dependencies. mavenCentral() + mavenLocal() + maven { + url 'https://frcmaven.wpi.edu/artifactory/release/' + } + maven { + url = uri("https://maven.pkg.github.com/Mechanical-Advantage/AdvantageKit") + credentials { + username = "Mechanical-Advantage-Bot" + password = "\u0067\u0068\u0070\u005f\u006e\u0056\u0051\u006a\u0055\u004f\u004c\u0061\u0079\u0066\u006e\u0078\u006e\u0037\u0051\u0049\u0054\u0042\u0032\u004c\u004a\u006d\u0055\u0070\u0073\u0031\u006d\u0037\u004c\u005a\u0030\u0076\u0062\u0070\u0063\u0051" + } + } + gradlePluginPortal() + maven { + name "photonvisionRepositoryReleases" + url "https://maven.photonvision.org/releases" + } } + spotless { // optional: limit format enforcement to just the files changed by this feature branch ratchetFrom 'origin/main' @@ -38,34 +115,7 @@ java { } } -compileJava.dependsOn 'spotlessApply' - - -dependencies { - // Use JUnit Jupiter for testing. - testImplementation libs.junit.jupiter - - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - - // This dependency is exported to consumers, that is to say found on their compile classpath. - api libs.commons.math3 - - // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation libs.guava -} - -// Apply a specific Java toolchain to ease working on different environments. -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} - +// Automatically format code on build. compileJava.dependsOn 'spotlessApply' @@ -80,7 +130,7 @@ mavenPublishing { pom { name = project.name inceptionYear = "2024" - description = 'FRC 401 core controls library' + description = 'FRC 401 core vision library' url = 'http://www.github.com/team401/coppercore' licenses { license { diff --git a/controls/src/main/java/LoggedTunableNumber.java b/controls/src/main/java/LoggedTunableNumber.java new file mode 100644 index 0000000..9af4237 --- /dev/null +++ b/controls/src/main/java/LoggedTunableNumber.java @@ -0,0 +1,120 @@ +// Copyright (c) 2024 FRC 6328 +// http://github.com/Mechanical-Advantage +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file at +// the root directory of this project. + +package coppercore.controls; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.DoubleSupplier; +import org.littletonrobotics.junction.networktables.LoggedDashboardNumber; + +/** + * Class for a tunable number. Gets value from dashboard in tuning mode, returns default if not or + * value not in dashboard. + */ +public class LoggedTunableNumber implements DoubleSupplier { + private static final String tableKey = "TunableNumbers"; + + private final String key; + private boolean hasDefault = false; + private double defaultValue; + private LoggedDashboardNumber dashboardNumber; + private Map lastHasChangedValues = new HashMap<>(); + private BooleanSupplier condition = () -> true; + + /** + * Create a new LoggedTunableNumber with the default value + * + * @param dashboardKey Key on dashboard + * @param defaultValue Default value + */ + public LoggedTunableNumber(String dashboardKey, double defaultValue) { + this.key = tableKey + "/" + dashboardKey; + initDefault(defaultValue); + } + + /** + * Set the default value of the number. The default value can only be set once. + * + * @param defaultValue The default value + */ + private void initDefault(double defaultValue) { + if (!hasDefault) { + hasDefault = true; + this.defaultValue = defaultValue; + if (condition.getAsBoolean()) { + dashboardNumber = new LoggedDashboardNumber(key, defaultValue); + } + } + } + + public void setInitCondition(BooleanSupplier condition) { + this.condition = condition; + } + + /** + * Get the current value, from dashboard if available and in tuning mode. + * + * @return The current value + */ + @Override + public double getAsDouble() { + if (!hasDefault) { + return 0.0; + } else { + return condition.getAsBoolean() && dashboardNumber != null + ? dashboardNumber.get() + : defaultValue; + } + } + + /** + * Checks whether the number has changed since our last check + * + * @param id Unique identifier for the caller to avoid conflicts when shared between multiple + * objects. Recommended approach is to pass the result of "hashCode()" + * @return True if the number has changed since the last time this method was called, false + * otherwise. + */ + public boolean hasChanged(int id) { + double currentValue = getAsDouble(); + Double lastValue = lastHasChangedValues.get(id); + if (lastValue == null || currentValue != lastValue) { + lastHasChangedValues.put(id, currentValue); + return true; + } + + return false; + } + + /** + * Runs action if any of the tunableNumbers have changed + * + * @param id Unique identifier for the caller to avoid conflicts when shared between multiple * + * objects. Recommended approach is to pass the result of "hashCode()" + * @param action Callback to run when any of the tunable numbers have changed. Access tunable + * numbers in order inputted in method + * @param tunableNumbers All tunable numbers to check + */ + public static void ifChanged( + int id, Consumer action, LoggedTunableNumber... tunableNumbers) { + if (Arrays.stream(tunableNumbers).anyMatch(tunableNumber -> tunableNumber.hasChanged(id))) { + action.accept( + Arrays.stream(tunableNumbers) + .mapToDouble(LoggedTunableNumber::getAsDouble) + .toArray()); + } + } + + /** Runs action if any of the tunableNumbers have changed */ + public static void ifChanged(int id, Runnable action, LoggedTunableNumber... tunableNumbers) { + ifChanged(id, values -> action.run(), tunableNumbers); + } +} diff --git a/controls/src/vendordeps/AdvantageKit.json b/controls/src/vendordeps/AdvantageKit.json new file mode 100644 index 0000000..5fda88d --- /dev/null +++ b/controls/src/vendordeps/AdvantageKit.json @@ -0,0 +1,42 @@ +{ + "fileName": "AdvantageKit.json", + "name": "AdvantageKit", + "version": "3.2.1", + "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", + "frcYear": "2024", + "mavenUrls": [], + "jsonUrl": "https://github.com/Mechanical-Advantage/AdvantageKit/releases/latest/download/AdvantageKit.json", + "javaDependencies": [ + { + "groupId": "org.littletonrobotics.akit.junction", + "artifactId": "wpilib-shim", + "version": "3.2.1" + }, + { + "groupId": "org.littletonrobotics.akit.junction", + "artifactId": "junction-core", + "version": "3.2.1" + }, + { + "groupId": "org.littletonrobotics.akit.conduit", + "artifactId": "conduit-api", + "version": "3.2.1" + } + ], + "jniDependencies": [ + { + "groupId": "org.littletonrobotics.akit.conduit", + "artifactId": "conduit-wpilibio", + "version": "3.2.1", + "skipInvalidPlatforms": false, + "isJar": false, + "validPlatforms": [ + "linuxathena", + "windowsx86-64", + "linuxx86-64", + "osxuniversal" + ] + } + ], + "cppDependencies": [] +} \ No newline at end of file diff --git a/controls/src/vendordeps/WPILibNewCommands.json b/controls/src/vendordeps/WPILibNewCommands.json new file mode 100644 index 0000000..4d1a3d4 --- /dev/null +++ b/controls/src/vendordeps/WPILibNewCommands.json @@ -0,0 +1,38 @@ +{ + "fileName": "WPILibNewCommands.json", + "name": "WPILib-New-Commands", + "version": "1.0.0", + "uuid": "111e20f7-815e-48f8-9dd6-e675ce75b266", + "frcYear": "2024", + "mavenUrls": [], + "jsonUrl": "", + "javaDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-java", + "version": "wpilib" + } + ], + "jniDependencies": [], + "cppDependencies": [ + { + "groupId": "edu.wpi.first.wpilibNewCommands", + "artifactId": "wpilibNewCommands-cpp", + "version": "wpilib", + "libName": "wpilibNewCommands", + "headerClassifier": "headers", + "sourcesClassifier": "sources", + "sharedLibrary": true, + "skipInvalidPlatforms": true, + "binaryPlatforms": [ + "linuxathena", + "linuxarm32", + "linuxarm64", + "windowsx86-64", + "windowsx86", + "linuxx86-64", + "osxuniversal" + ] + } + ] +} \ No newline at end of file diff --git a/wpilib_interface/src/main/java/frc/robot/BuildConstants.java b/wpilib_interface/src/main/java/frc/robot/BuildConstants.java index 09c9ba9..6b959f2 100644 --- a/wpilib_interface/src/main/java/frc/robot/BuildConstants.java +++ b/wpilib_interface/src/main/java/frc/robot/BuildConstants.java @@ -5,12 +5,12 @@ public final class BuildConstants { public static final String MAVEN_GROUP = "io.github.team401.coppercore"; public static final String MAVEN_NAME = "wpilib_interface"; public static final String VERSION = "2025.0.0-beta"; - public static final int GIT_REVISION = 42; - public static final String GIT_SHA = "ae92bd015cfea62f3e15e05ecaa129c58aa316b1"; - public static final String GIT_DATE = "2024-12-06 12:09:14 EST"; - public static final String GIT_BRANCH = "64-clamp-measures"; - public static final String BUILD_DATE = "2024-12-07 23:05:47 EST"; - public static final long BUILD_UNIX_TIME = 1733630747090L; + public static final int GIT_REVISION = 44; + public static final String GIT_SHA = "ddc04e079cba49e2817a35376e6239576d1dba13"; + public static final String GIT_DATE = "2024-12-09 10:33:47 EST"; + public static final String GIT_BRANCH = "73-add-logged-tunable-number-to-coppercore"; + public static final String BUILD_DATE = "2024-12-22 16:53:37 EST"; + public static final long BUILD_UNIX_TIME = 1734904417196L; public static final int DIRTY = 1; private BuildConstants() {}