From 18aeea1d8ec130e803b61501a67f53881c126435 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 19 Aug 2024 19:21:49 -0400 Subject: [PATCH] unclear if works ? --- wpi_interface/build.gradle | 211 +++++++++++-- .../src/main/java/ControllerJSONReader.java | 280 ++++++++++++++++++ wpi_interface/src/test/unittest.java | 4 + 3 files changed, 470 insertions(+), 25 deletions(-) create mode 100644 wpi_interface/src/main/java/ControllerJSONReader.java create mode 100644 wpi_interface/src/test/unittest.java diff --git a/wpi_interface/build.gradle b/wpi_interface/build.gradle index fe89829..7d94fb1 100644 --- a/wpi_interface/build.gradle +++ b/wpi_interface/build.gradle @@ -1,41 +1,202 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * This generated file contains a sample Java library project to get you started. - * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.7/userguide/building_java_projects.html in the Gradle documentation. - */ +import java.text.SimpleDateFormat plugins { - // Apply the java-library plugin for API and implementation separation. - id 'java-library' + id "java" + id "edu.wpi.first.GradleRIO" version "2024.3.2" + id "com.peterabeles.gversion" version "1.10" + id "com.diffplug.spotless" version "6.24.0" + id 'org.ajoberstar.grgit' version "5.2.1" } -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +def ROBOT_MAIN_CLASS = "frc.robot.Main" + +def VISUALVM_PROFILE = false + +// Define my targets (RoboRIO) and artifacts (deployable files) +// This is added by GradleRIO's backing project DeployUtils. +deploy { + targets { + roborio(getTargetTypeClass('RoboRIO')) { + // Team number is loaded either from the .wpilib/wpilib_preferences.json + // or from command line. If not found an exception will be thrown. + // You can use getTeamOrDefault(team) instead of getTeamNumber if you + // want to store a team number in this file. + team = project.frc.getTeamNumber() + debug = project.frc.getDebugOrDefault(false) + + artifacts { + // First part is artifact name, 2nd is artifact type + // getTargetTypeClass is a shortcut to get the class type using a string + + frcJava(getArtifactTypeClass('FRCJavaArtifact')) { + // jvmArgs.add("-XX:MaxHeapFreeRatio 40") + + if (VISUALVM_PROFILE) { + // Enable VisualVM connection + jvmArgs.add("-Dcom.sun.management.jmxremote=true") + jvmArgs.add("-Dcom.sun.management.jmxremote.port=1198") + jvmArgs.add("-Dcom.sun.management.jmxremote.local.only=false") + jvmArgs.add("-Dcom.sun.management.jmxremote.ssl=false") + jvmArgs.add("-Dcom.sun.management.jmxremote.authenticate=false") + jvmArgs.add("-Djava.rmi.server.hostname=10.4.1.2") + } + } + + // Static files artifact + frcStaticFileDeploy(getArtifactTypeClass('FileTreeArtifact')) { + files = project.fileTree('src/main/deploy') + directory = '/home/lvuser/deploy' + } + } + } + } } +def deployArtifact = deploy.targets.roborio.artifacts.frcJava + +// Set to true to use debug for JNI. +wpi.java.debugJni = false + +// Set this to true to enable desktop support. +def includeDesktopSupport = true + +// Defining my dependencies. In this case, WPILib (+ friends), and vendor libraries. +// Also defines JUnit 5. dependencies { - // Use JUnit Jupiter for testing. - testImplementation libs.junit.jupiter + // ... + def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text) + annotationProcessor "org.littletonrobotics.akit.junction:junction-autolog:$akitJson.version" + + implementation wpi.java.deps.wpilib() + implementation wpi.java.vendor.java() + + roborioDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.roborio) + roborioDebug wpi.java.vendor.jniDebug(wpi.platforms.roborio) - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio) + roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio) - // This dependency is exported to consumers, that is to say found on their compile classpath. - api libs.commons.math3 + nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop) + nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop) + simulationDebug wpi.sim.enableDebug() - // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation libs.guava + nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop) + nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop) + simulationRelease wpi.sim.enableRelease() + + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +test { + useJUnitPlatform() + systemProperty 'junit.jupiter.extensions.autodetection.enabled', 'true' } -// Apply a specific Java toolchain to ease working on different environments. +// Simulation configuration (e.g. environment variables). +wpi.sim.addGui().defaultEnabled = true +wpi.sim.addDriverstation() + +// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar') +// in order to make them all available at runtime. Also adding the manifest so WPILib +// knows where to look for our Robot Class. +jar { + from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } + from sourceSets.main.allSource + manifest edu.wpi.first.gradlerio.GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) + duplicatesStrategy = DuplicatesStrategy.INCLUDE +} + +// Configure jar and deploy tasks +deployArtifact.jarTask = jar +wpi.java.configureExecutableTasks(jar) +wpi.java.configureTestTasks(test) + +// 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 { + 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" + } + } + mavenLocal() +} + +spotless { +// optional: limit format enforcement to just the files changed by this feature branch +ratchetFrom 'origin/main' + +format 'misc', { + // define the files to apply `misc` to + target '*.gradle', '.gitattributes', '.gitignore' + + // define the steps to apply to those files + trimTrailingWhitespace() + indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 + endWithNewline() +} java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } + // don't need to set target, it is inferred from java + // Allow ignoring certain parts in formatting. + toggleOffOn() + // apply a specific flavor of google-java-format + googleJavaFormat('1.19.2').aosp().reflowLongStrings() + // fix formatting of type annotations + formatAnnotations() +} } -tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() +// Automatically format code on build. +compileJava.dependsOn 'spotlessApply' + +configurations.all { + exclude group: "edu.wpi.first.wpilibj" } + +task(checkAkitInstall, dependsOn: "classes", type: JavaExec) { + mainClass = "org.littletonrobotics.junction.CheckInstall" + classpath = sourceSets.main.runtimeClasspath +} +compileJava.finalizedBy checkAkitInstall + +task (commitOnDeploy, dependsOn: "spotlessApply") { + description = 'Commits when deployed.' + doLast { + if (true) { + def date = new Date() + def sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss") + grgit.add(patterns: [ + 'src/', + 'vendordeps/', + 'build.gradle', + 'logs', + 'gradle', + '.wpilib' + ]) + grgit.commit(message: "Automated commit at " + sdf.format(date), all: true) + } + } +} + +// compileJava.dependsOn commitOnDeploy \ No newline at end of file diff --git a/wpi_interface/src/main/java/ControllerJSONReader.java b/wpi_interface/src/main/java/ControllerJSONReader.java new file mode 100644 index 0000000..334717a --- /dev/null +++ b/wpi_interface/src/main/java/ControllerJSONReader.java @@ -0,0 +1,280 @@ +package coppercore.wpilib_interface; + +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.Filesystem; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.button.CommandGenericHID; +import edu.wpi.first.wpilibj2.command.button.CommandJoystick; +import edu.wpi.first.wpilibj2.command.button.CommandXboxController; +import edu.wpi.first.wpilibj2.command.button.Trigger; +import java.io.File; +import java.io.FileReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.function.DoubleSupplier; +import java.util.function.IntSupplier; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +public class ControllerJSONReader { + + private static HashMap controllers; + + private static HashMap triggers; + private static HashMap axes; + private static HashMap pov; + + // gets json objects from chosen json file + public static void pullConfiguration(String configuration) { + JSONParser jsonParser = new JSONParser(); + JSONObject jsonObject; + try { + jsonObject = + (JSONObject) + jsonParser.parse( + (new FileReader( + new File( + Filesystem.getDeployDirectory(), + "controllerconfig/" + + configuration + + ".json")))); + + } catch (Exception e) { + throw new RuntimeException("Controller not found, please try again"); + } + setControllers((JSONArray) jsonObject.get("controllers")); + setTriggers((JSONArray) jsonObject.get("buttons")); + setAxes((JSONArray) jsonObject.get("axes")); + setPOV((JSONArray) jsonObject.get("pov")); + } + + // initializes controllers based on json file data + private static HashMap setControllers(JSONArray controllersJSON) { + HashMap controllersList = + new HashMap(); + Iterator iterator = controllersJSON.iterator(); + while (iterator.hasNext()) { + // initializes each controller + JSONObject controller = iterator.next(); + // joysticks + if (((String) controller.get("type")).equals("joystick")) { + controllersList.put( + ((Long) controller.get("port")).intValue(), + new CommandJoystick(((Long) controller.get("port")).intValue())); + } else { + // xbox controller + controllersList.put( + ((Long) controller.get("port")).intValue(), + new CommandXboxController(((Long) controller.get("port")).intValue())); + } + } + controllers = controllersList; + return controllersList; + } + + // assigns triggers to string keys + private static HashMap setTriggers(JSONArray triggersJSON) { + HashMap triggerList = new HashMap(); + Iterator iterator = triggersJSON.iterator(); + while (iterator.hasNext()) { + JSONObject trigger = iterator.next(); + Trigger t; + + int port = ((Long) trigger.get("controller")).intValue(); + + // first case is for xbox controllers, second case is for joysticks + switch (((String) trigger.get("button"))) { + case "a": + case "1": + t = controllers.get(port).button(1); + break; + case "b": + case "2": + t = controllers.get(port).button(2); + break; + case "x": + case "3": + t = controllers.get(port).button(3); + break; + case "y": + case "4": + t = controllers.get(port).button(4); + break; + case "leftBumper": + case "5": + t = controllers.get(port).button(5); + break; + case "rightBumper": + case "6": + t = controllers.get(port).button(6); + break; + case "back": + case "7": + t = controllers.get(port).button(7); + break; + case "start": + case "8": + t = controllers.get(port).button(8); + break; + case "leftJoystickPress": + case "9": + t = controllers.get(port).button(9); + break; + case "rightJoystickPress": + case "10": + t = controllers.get(port).button(10); + break; + case "pov0": + t = controllers.get(port).pov(0); + break; + case "pov45": + t = controllers.get(port).pov(45); + break; + case "pov90": + t = controllers.get(port).pov(90); + break; + case "pov135": + t = controllers.get(port).pov(135); + break; + case "pov180": + t = controllers.get(port).pov(180); + break; + case "pov225": + t = controllers.get(port).pov(225); + break; + case "pov270": + t = controllers.get(port).pov(270); + break; + case "pov315": + t = controllers.get(port).pov(315); + break; + case "povCenter": + t = controllers.get(port).pov(-1); + break; + default: + t = null; + DriverStation.reportError( + "Trigger" + (String) trigger.get("button") + "not found", false); + break; + } + + triggerList.put((String) trigger.get("command"), t); + } + triggers = triggerList; + return triggerList; + } + + // assigns axis doublesuppliers to string keys + private static HashMap setAxes(JSONArray axisJSON) { + HashMap axisList = new HashMap(); + Iterator iterator = axisJSON.iterator(); + while (iterator.hasNext()) { + JSONObject axis = iterator.next(); + DoubleSupplier t; + + int port = ((Long) axis.get("controller")).intValue(); + + // first case is for xbox controller, second case is for joysticks + switch (((String) axis.get("axis"))) { + case "leftX": + case "xAxis": + if ((boolean) axis.get("negate")) + t = () -> -controllers.get(port).getRawAxis(0); + else t = () -> controllers.get(port).getRawAxis(0); + SmartDashboard.putNumber("readaxis", t.getAsDouble()); + break; + case "leftY": + case "yAxis": + if ((boolean) axis.get("negate")) + t = () -> -controllers.get(port).getRawAxis(1); + else t = () -> controllers.get(port).getRawAxis(1); + break; + case "leftTrigger": + case "zRotate": + if ((boolean) axis.get("negate")) + t = () -> -controllers.get(port).getRawAxis(2); + else t = () -> controllers.get(port).getRawAxis(2); + break; + case "rightTrigger": + case "slider": + if ((boolean) axis.get("negate")) + t = () -> -controllers.get(port).getRawAxis(3); + else t = () -> controllers.get(port).getRawAxis(3); + break; + case "rightX": + if ((boolean) axis.get("negate")) + t = () -> -controllers.get(port).getRawAxis(4); + else t = () -> controllers.get(port).getRawAxis(4); + break; + case "rightY": + if ((boolean) axis.get("negate")) + t = () -> -controllers.get(port).getRawAxis(5); + else t = () -> controllers.get(port).getRawAxis(5); + break; + default: + t = null; + DriverStation.reportError( + "Axis" + (String) axis.get("button") + "not found", false); + break; + } + + axisList.put((String) axis.get("command"), t); + } + axes = axisList; + return axisList; + } + + // assigns pov intsuppliers to string keys + private static HashMap setPOV(JSONArray povJSON) { + HashMap povList = new HashMap(); + Iterator iterator = povJSON.iterator(); + while (iterator.hasNext()) { + JSONObject p = iterator.next(); + + if (controllers.get(p.get("controller")) == null) { + povList.put((String) p.get("command"), () -> 0); + DriverStation.reportError("POV" + (String) p.get("command") + "not found", false); + } else + povList.put( + (String) p.get("command"), + () -> controllers.get(p.get("controller")).getHID().getPOV()); + } + pov = povList; + return povList; + } + + // methods to get controllers, triggers, axes, povs for robotcontainer use + + public static HashMap getControllers() { + if (controllers == null) { + throw new RuntimeException("Controllers not yet generated, run pullConfiguration"); + } else { + return controllers; + } + } + + public static HashMap getTriggers() { + if (triggers == null) { + throw new RuntimeException("Triggers not yet generated, run pullConfiguration"); + } else { + return triggers; + } + } + + public static HashMap getAxes() { + if (axes == null) { + throw new RuntimeException("Axes not yet generated, run pullConfiguration"); + } else { + return axes; + } + } + + public static HashMap getPOVs() { + if (pov == null) { + throw new RuntimeException("POVs not yet generated, run pullConfiguration"); + } else { + return pov; + } + } +} \ No newline at end of file diff --git a/wpi_interface/src/test/unittest.java b/wpi_interface/src/test/unittest.java new file mode 100644 index 0000000..44fb55b --- /dev/null +++ b/wpi_interface/src/test/unittest.java @@ -0,0 +1,4 @@ +public class unittest { + + // +}