diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76a88d3..15707f4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 + with: + submodules: 'true' - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@v1 - name: Setup JDK diff --git a/.gitignore b/.gitignore index be03bf9..7116549 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -src/main/java/BuildConstants.java - # Dynamically generated by IntelliJ IDEA FRC Plugin on Tuesday May 16, 2023 1:48:30 PM PDT # using https://www.toptal.com/developers/gitignore/api (See https://docs.gitignore.io) # Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij+all,visualstudiocode,eclipse,netbeans,linux,macos,windows diff --git a/.wpilib/wpilib_preferences.json b/.wpilib/wpilib_preferences.json index 3456724..d79e2f9 100644 --- a/.wpilib/wpilib_preferences.json +++ b/.wpilib/wpilib_preferences.json @@ -1,6 +1,6 @@ { "enableCppIntellisense": false, "currentLanguage": "java", - "projectYear": "2023", + "projectYear": "2024", "teamNumber": 3636 } \ No newline at end of file diff --git a/annotation/LICENSE b/annotation/LICENSE new file mode 100644 index 0000000..54deed8 --- /dev/null +++ b/annotation/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Team 8-Bit 9432 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/annotation/build.gradle.kts b/annotation/build.gradle.kts new file mode 100644 index 0000000..aa385b0 --- /dev/null +++ b/annotation/build.gradle.kts @@ -0,0 +1,21 @@ +val kspVersion: String by project + +plugins { + kotlin("jvm") +} + +group = "org.team9432.lib" + +dependencies { + implementation("com.squareup:kotlinpoet:1.14.2") + implementation("com.squareup:kotlinpoet-ksp:1.14.2") + implementation("com.google.devtools.ksp:symbol-processing-api:$kspVersion") + + implementation("org.littletonrobotics.akit.junction:junction-core:3.2.1") +} + +repositories { + maven { + url = uri("https://frcmaven.wpi.edu/artifactory/release/") + } +} diff --git a/annotation/src/main/kotlin/org/team9432/annotation/LogTableUtils.kt b/annotation/src/main/kotlin/org/team9432/annotation/LogTableUtils.kt new file mode 100644 index 0000000..b2d31fb --- /dev/null +++ b/annotation/src/main/kotlin/org/team9432/annotation/LogTableUtils.kt @@ -0,0 +1,63 @@ +package org.team9432.annotation + +import edu.wpi.first.units.Measure +import edu.wpi.first.units.MutableMeasure +import edu.wpi.first.units.Unit +import edu.wpi.first.util.WPISerializable +import edu.wpi.first.util.protobuf.Protobuf +import edu.wpi.first.util.struct.Struct +import edu.wpi.first.util.struct.StructSerializable +import org.littletonrobotics.junction.LogTable +import org.littletonrobotics.junction.LogTable.LogValue +import us.hebi.quickbuf.ProtoMessage + +object LogTableUtils { + // This is all just to get correct type inference working with kotlin + fun LogTable.kGet(key: String, defaultValue: T) = this.getFromWPISerializable(key, defaultValue) + private fun LogTable.getFromWPISerializable(key: String, defaultValue: T): T = this.get(key, defaultValue) + + fun LogTable.kPut(key: String, value: LogValue) = put(key, value) + fun LogTable.kPut(key: String, value: ByteArray) = put(key, value) + fun LogTable.kPut(key: String, value: Boolean) = put(key, value) + fun LogTable.kPut(key: String, value: Int) = put(key, value) + fun LogTable.kPut(key: String, value: Long) = put(key, value) + fun LogTable.kPut(key: String, value: Float) = put(key, value) + fun LogTable.kPut(key: String, value: Double) = put(key, value) + fun LogTable.kPut(key: String, value: String) = put(key, value) + fun > LogTable.kPut(key: String, value: E) = put(key, value) + fun > LogTable.kPut(key: String, value: Measure) = put(key, value) + fun LogTable.kPut(key: String, value: BooleanArray) = put(key, value) + fun LogTable.kPut(key: String, value: IntArray) = put(key, value) + fun LogTable.kPut(key: String, value: LongArray) = put(key, value) + fun LogTable.kPut(key: String, value: FloatArray) = put(key, value) + fun LogTable.kPut(key: String, value: DoubleArray) = put(key, value) + fun LogTable.kPut(key: String, value: Array) = put(key, value) + fun LogTable.kPut(key: String, struct: Struct, value: T) = put(key, struct, value) + fun LogTable.kPut(key: String, struct: Struct, value: Array) = put(key, struct, *value) + fun > LogTable.kPut(key: String, proto: Protobuf, value: T) = put(key, proto, value) + fun LogTable.kPut(key: String, value: T) = put(key, value) + fun LogTable.kPut(key: String, value: Array) = put(key, *value) + + fun LogTable.kGet(key: String): LogValue = get(key) + fun LogTable.kGet(key: String, defaultValue: ByteArray): ByteArray = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: Boolean) = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: Int) = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: Long) = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: Float) = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: Double) = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: String): String = get(key, defaultValue) + fun > LogTable.kGet(key: String, defaultValue: E): E = get(key, defaultValue) + fun > LogTable.kGet(key: String, defaultValue: Measure): Measure = get(key, defaultValue) + fun > LogTable.kGet(key: String, defaultValue: MutableMeasure): MutableMeasure = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: BooleanArray): BooleanArray = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: IntArray): IntArray = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: LongArray): LongArray = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: FloatArray): FloatArray = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: DoubleArray): DoubleArray = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: Array): Array = get(key, defaultValue) + fun LogTable.kGet(key: String, struct: Struct, defaultValue: T): T = get(key, struct, defaultValue) + fun LogTable.kGet(key: String, struct: Struct, defaultValue: Array): Array = get(key, struct, *defaultValue) + fun > LogTable.kGet(key: String, proto: Protobuf, defaultValue: T): T = get(key, proto, defaultValue) + fun LogTable.kGet(key: String, defaultValue: T): T = get(key, defaultValue) + fun LogTable.kGet(key: String, defaultValue: Array): Array = get(key, *defaultValue) +} \ No newline at end of file diff --git a/annotation/src/main/kotlin/org/team9432/annotation/Logged.kt b/annotation/src/main/kotlin/org/team9432/annotation/Logged.kt new file mode 100644 index 0000000..5b0bffd --- /dev/null +++ b/annotation/src/main/kotlin/org/team9432/annotation/Logged.kt @@ -0,0 +1,4 @@ +package org.team9432.annotation + +@Target(AnnotationTarget.CLASS) +annotation class Logged \ No newline at end of file diff --git a/annotation/src/main/kotlin/org/team9432/annotation/LoggedProcessor.kt b/annotation/src/main/kotlin/org/team9432/annotation/LoggedProcessor.kt new file mode 100644 index 0000000..35c7f1d --- /dev/null +++ b/annotation/src/main/kotlin/org/team9432/annotation/LoggedProcessor.kt @@ -0,0 +1,81 @@ +package org.team9432.annotation + +import com.google.devtools.ksp.processing.* +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.Modifier +import com.google.devtools.ksp.validate +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.FunSpec +import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.TypeSpec +import com.squareup.kotlinpoet.ksp.toClassName +import com.squareup.kotlinpoet.ksp.writeTo +import org.littletonrobotics.junction.LogTable +import org.littletonrobotics.junction.inputs.LoggableInputs + +class LoggedProcessor(private val codeGenerator: CodeGenerator): SymbolProcessor { + private val logTableType = LogTable::class + private val loggableInputsType = LoggableInputs::class + + override fun process(resolver: Resolver): List { + val annotatedClasses = resolver.getSymbolsWithAnnotation("org.team9432.annotation.Logged").filterIsInstance() + annotatedClasses.forEach { process(it) } + return annotatedClasses.filterNot { it.validate() }.toList() + } + + private fun process(classDeclaration: KSClassDeclaration) { + if (!classDeclaration.modifiers.contains(Modifier.OPEN)) throw Exception("""[Logged] Please ensure the class you are annotating (${classDeclaration.simpleName.asString()}) has the open modifier!""") + + val packageName = classDeclaration.packageName.asString() + val className = classDeclaration.simpleName.asString() + + val newClassName = "Logged${className}" + + val toLogBuilder = FunSpec.builder("toLog") + .addModifiers(KModifier.OVERRIDE) + .addParameter("table", logTableType) + val fromLogBuilder = FunSpec.builder("fromLog") + .addModifiers(KModifier.OVERRIDE) + .addParameter("table", logTableType) + + classDeclaration.getAllProperties().forEach { property -> + val simpleName = property.simpleName.asString() + val logName = simpleName.substring(0, 1).uppercase() + simpleName.substring(1) + + if (!property.isMutable) throw Exception("""[Logged] Please ensure the class you are annotating (${classDeclaration.simpleName.asString()}.${simpleName}) has only mutable properties!""") + + toLogBuilder.addCode( + """ |table.kPut("$logName", $simpleName) + | + """.trimMargin() + ) + + fromLogBuilder.addCode( + """ |$simpleName = table.kGet("$logName", $simpleName) + | + """.trimMargin() + ) + } + + val type = TypeSpec.classBuilder(newClassName) + .addSuperinterface(loggableInputsType) + .superclass(classDeclaration.toClassName()) + .addFunction(toLogBuilder.build()) + .addFunction(fromLogBuilder.build()) + + + val file = FileSpec.builder(packageName, newClassName) + file.addType(type.build()) + file.indent(" ") + file.addImport(LogTableUtils::class, "kGet", "kPut") + file.addImport("com.frcteam3636.frc2024.utils.LogTableUtils", "kGet", "kPut") + file.build().writeTo(codeGenerator, Dependencies(true, classDeclaration.containingFile!!)) + } +} + +class Provider: SymbolProcessorProvider { + override fun create(environment: SymbolProcessorEnvironment) = LoggedProcessor( + codeGenerator = environment.codeGenerator + ) +} \ No newline at end of file diff --git a/annotation/src/main/kotlin/org/team9432/annotation/README.md b/annotation/src/main/kotlin/org/team9432/annotation/README.md new file mode 100644 index 0000000..9c8be6f --- /dev/null +++ b/annotation/src/main/kotlin/org/team9432/annotation/README.md @@ -0,0 +1,4 @@ +## org/team9432/lib/annotation/ + +This package is for a custom annotation processor that replicates the behavior of AdvantageKit's AutoLog annotation, but +in Kotlin. \ No newline at end of file diff --git a/annotation/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/annotation/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider new file mode 100644 index 0000000..4490827 --- /dev/null +++ b/annotation/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider @@ -0,0 +1 @@ +org.team9432.annotation.Provider \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index ffa7836..0000000 --- a/build.gradle +++ /dev/null @@ -1,158 +0,0 @@ -//file:noinspection DependencyNotationArgument -import edu.wpi.first.gradlerio.GradleRIOPlugin -import groovy.json.JsonSlurper -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -plugins { - id "java" - id "org.jetbrains.kotlin.jvm" version "1.9.22" - id "edu.wpi.first.GradleRIO" version "2024.1.1" - id "com.peterabeles.gversion" version "1.10" - id "idea" -} - -def javaVersion = JavaVersion.VERSION_17 - -java { - sourceCompatibility = javaVersion - targetCompatibility = javaVersion -} - -def ROBOT_MAIN_CLASS = "com.frcteam3636.frc2024.Main" - -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() -} - -configurations.configureEach { - exclude group: "edu.wpi.first.wpilibj" -} - -tasks.register('checkAkitInstall', JavaExec) { - dependsOn "classes" - mainClass = "org.littletonrobotics.junction.CheckInstall" - classpath = sourceSets.main.runtimeClasspath -} -compileJava.finalizedBy checkAkitInstall - -project.assemble.dependsOn(createVersionFile) -gversion { - srcDir = "src/main/java/" - classPackage = "" - className = "BuildConstants" - dateFormat = "yyyy-MM-dd HH:mm:ss z" - timeZone = "America/Los_Angeles" // Use preferred time zone - indent = " " -} - -// 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("-ea") // Remove this flag during comp to disable asserts - } - - // 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 - -dependencies { - 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) - - roborioRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.roborio) - roborioRelease wpi.java.vendor.jniRelease(wpi.platforms.roborio) - - nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop) - nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop) - simulationDebug wpi.sim.enableDebug() - - nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop) - nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop) - simulationRelease wpi.sim.enableRelease() - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - - def akitJson = new JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text) - annotationProcessor "org.littletonrobotics.akit.junction:junction-autolog:$akitJson.version" -} - -// 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 GradleRIOPlugin.javaManifest(ROBOT_MAIN_CLASS) - duplicatesStrategy = DuplicatesStrategy.INCLUDE -} - -// Configure jar and deploy tasks -deployArtifact.jarTask = jar -wpi.java.configureExecutableTasks(jar) -wpi.java.configureTestTasks(test) - -tasks.withType(JavaCompile).configureEach { - // Configure string concat to always inline compile - options.compilerArgs.add '-XDstringConcat=inline' -} - -kotlin { - compilerOptions { - jvmTarget.set(JvmTarget.@Companion.fromTarget(javaVersion.toString())) - // https://kotlinlang.org/docs/gradle-configure-project.html#gradle-java-toolchains-support - jvmToolchain(Integer.valueOf(javaVersion.toString())) - } -} - -idea { - project { - // The project.sourceCompatibility setting is not always picked up, so we set explicitly - languageLevel = javaVersion - } - module { - // Improve development & (especially) debugging experience (and IDEA's capabilities) by having libraries' source & javadoc attached - downloadJavadoc = true - downloadSources = true - // Exclude the .vscode directory from indexing and search - excludeDirs+=file(".vscode" ) - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..ce652e2 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,195 @@ +import edu.wpi.first.deployutils.deploy.artifact.FileTreeArtifact +import edu.wpi.first.gradlerio.GradleRIOPlugin +import edu.wpi.first.gradlerio.deploy.roborio.FRCJavaArtifact +import edu.wpi.first.gradlerio.deploy.roborio.RoboRIO +import edu.wpi.first.toolchain.NativePlatforms +import org.gradle.plugins.ide.idea.model.IdeaLanguageLevel +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + java + idea + kotlin("jvm") + id("com.google.devtools.ksp") + id("edu.wpi.first.GradleRIO") version "2024.3.2" + id("com.peterabeles.gversion") version "1.10" +} + +val javaVersion = 17 +val robotMainClass = "com.frcteam3636.frc2024.Main" + +allprojects { + plugins.apply("java") + plugins.apply("org.jetbrains.kotlin.jvm") + + java { + val version = JavaVersion.toVersion(javaVersion) + sourceCompatibility = version + targetCompatibility = version + } + + kotlin { + compilerOptions { + // https://kotlinlang.org/docs/gradle-configure-project.html#gradle-java-toolchains-support + jvmTarget = JvmTarget.fromTarget(javaVersion.toString()) + jvmToolchain(javaVersion) + } + } + + 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() + mavenCentral() + } +} + +gversion { + srcDir = layout.buildDirectory.dir("generated/gversion/main/kotlin").get().toString() + language = "kotlin" + classPackage = "com.frcteam3636.version" + dateFormat = "yyyy-MM-dd HH:mm:ss z" + timeZone = "America/Los_Angeles" // Use preferred time zone + indent = " " +} + +// Define the targets (RoboRIO) and artifacts (deployable files) +// This is added by GradleRIO's backing project DeployUtils. +deploy { + targets { + val roborio by register("roborio") { + // Team number is loaded either from the .wpilib/wpilib_preferences.json + // or from command line. If not found an exception will be thrown. + team = frc.getTeamOrDefault(3636) + debug = frc.getDebugOrDefault(false) + } + + roborio.artifacts { + register("frcJava") { + jvmArgs.add("-ea") // Remove this flag during comp to disable asserts + setJarTask(tasks.jar) + } + + register("frcStaticFileDeploy") { + files = project.fileTree("src/main/deploy") + directory = "/home/lvuser/deploy" + } + } + } +} + +configurations.configureEach { + exclude(group = "edu.wpi.first.wpilibj") +} + +wpi { + with(java) { + // Set to true to use debug for JNI. + debugJni = false + + // Configure jar and deploy tasks + configureExecutableTasks(tasks.jar.get()) + configureTestTasks(tasks.test.get()) + } + + // Simulation configuration (e.g. environment variables). + with(sim) { + addGui().defaultEnabled = true + addDriverstation().defaultEnabled = true + } +} + + +dependencies { + wpi.java.deps.wpilib().forEach { implementation(it) } + wpi.java.vendor.java().forEach { implementation(it) } + + wpi.java.deps.wpilibJniDebug(NativePlatforms.roborio).forEach { "roborioDebug"(it) } + wpi.java.vendor.jniDebug(NativePlatforms.roborio).forEach { "roborioDebug"(it) } + + wpi.java.deps.wpilibJniRelease(NativePlatforms.roborio).forEach { "roborioRelease"(it) } + wpi.java.vendor.jniRelease(NativePlatforms.roborio).forEach { "roborioRelease"(it) } + + wpi.java.deps.wpilibJniDebug(NativePlatforms.desktop).forEach { nativeDebug(it) } + wpi.java.vendor.jniDebug(NativePlatforms.desktop).forEach { nativeDebug(it) } + wpi.sim.enableDebug().forEach { simulationDebug(it) } + + wpi.java.deps.wpilibJniRelease(NativePlatforms.desktop).forEach { nativeRelease(it) } + wpi.java.vendor.jniRelease(NativePlatforms.desktop).forEach { nativeRelease(it) } + + wpi.sim.enableRelease().forEach { simulationRelease(it) } + + implementation(project(":annotation")) + ksp(project(":annotation")) + +// testImplementation(platform("io.kotest:kotest-bom:5.8.0")) +// testImplementation("io.kotest:kotest-runner-junit5") +// testImplementation("io.kotest:kotest-assertions-core") +// testImplementation("io.mockk:mockk:1.13.9") +} + +// Set up the 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. +tasks { + jar { + group = "build" + manifest(GradleRIOPlugin.javaManifest(robotMainClass)) + duplicatesStrategy = DuplicatesStrategy.INCLUDE + + from({ + configurations + .runtimeClasspath + .get() + .map { if (it.isDirectory) it else zipTree(it) } + }) + } + + test { + useJUnitPlatform() + } + + // This check is buggy, also it seems to be removed in AdvantageKit 2025 +// val checkAkitInstall by register("checkAkitInstall") { +// dependsOn("classes") +// mainClass = "org.littletonrobotics.junction.CheckInstall" +// classpath = sourceSets.main.get().runtimeClasspath +// } + + compileKotlin { + dependsOn(createVersionFile) +// finalizedBy(checkAkitInstall) + } + + register("cleanStaticFiles") { + commandLine = listOf("ssh", "admin@10.36.36.2", "rm", "-rf", "/home/lvuser/deploy") + } +} + +sourceSets { + main { + kotlin { + srcDir(gversion.srcDir) + } + } +} + +idea { + project { + // The project.sourceCompatibility setting is not always picked up, so we set explicitly + languageLevel = IdeaLanguageLevel(javaVersion) + } + module { + // Improve development & (especially) debugging experience (and IDEA's capabilities) by having libraries' source & javadoc attached + isDownloadJavadoc = true + isDownloadSources = true + // Exclude the .vscode directory from indexing and search + excludeDirs.add(file(".vscode")) + } +} diff --git a/cleanDeploy.sh b/cleanDeploy.sh deleted file mode 100644 index 688dcb6..0000000 --- a/cleanDeploy.sh +++ /dev/null @@ -1,2 +0,0 @@ -ssh admin@10.36.36.2 rm -rf /home/lvuser/deploy -./gradlew deploy \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..4a0de39 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +kspVersion=2.0.21-1.0.25 +kotlinVersion=2.0.21 +frcYear=2024 diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 091a37a..0000000 --- a/settings.gradle +++ /dev/null @@ -1,27 +0,0 @@ -import org.gradle.internal.os.OperatingSystem - -pluginManagement { - repositories { - mavenLocal() - gradlePluginPortal() - String frcYear = '2024' - File frcHome - if (OperatingSystem.current().isWindows()) { - String publicFolder = System.getenv('PUBLIC') - if (publicFolder == null) { - publicFolder = "C:\\Users\\Public" - } - def homeRoot = new File(publicFolder, "wpilib") - frcHome = new File(homeRoot, frcYear) - } else { - def userFolder = System.getProperty("user.home") - def homeRoot = new File(userFolder, "wpilib") - frcHome = new File(homeRoot, frcYear) - } - def frcHomeMaven = new File(frcHome, 'maven') - maven { - name 'frcHome' - url frcHomeMaven - } - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..c364830 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,30 @@ +pluginManagement { + val kotlinVersion: String by settings + val kspVersion: String by settings + val frcYear: String by settings + + plugins { + id("com.google.devtools.ksp") version kspVersion + kotlin("jvm") version kotlinVersion + } + + repositories { + mavenLocal() + gradlePluginPortal() + + val frcHome = if (System.getProperty("os.name").lowercase().contains("windows")) { + file(System.getenv("PUBLIC") ?: "C:\\Users\\Public") + } else { + file(System.getProperty("user.home")) + } + .resolve("wpilib") + .resolve(frcYear) + + maven { + name = "frcHome" + url = uri(frcHome.resolve("maven")) + } + } +} + +include("annotation") diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/intake/IntakeIO.kt b/src/main/java/com/frcteam3636/frc2024/subsystems/intake/IntakeIO.kt deleted file mode 100644 index 71aec8d..0000000 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/intake/IntakeIO.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.frcteam3636.frc2024.subsystems.intake -import com.frcteam3636.frc2024.CANSparkFlex -import com.frcteam3636.frc2024.REVMotorControllerId -import com.frcteam3636.frc2024.Robot -import com.frcteam3636.frc2024.utils.math.TAU -import com.revrobotics.CANSparkLowLevel -import edu.wpi.first.math.system.plant.DCMotor -import edu.wpi.first.units.Units.* -import edu.wpi.first.wpilibj.simulation.FlywheelSim -import org.littletonrobotics.junction.LogTable -import org.littletonrobotics.junction.inputs.LoggableInputs - - -interface IntakeIO { - class Inputs : LoggableInputs { - var rollerVelocity = RotationsPerSecond.zero() - var current = Amps.zero() - var position = Radians.zero() - - override fun toLog(table: LogTable) { - table.put("Intake Velocity", rollerVelocity) - table.put("Intake Current", current) - table.put("Intake Roller Position", position) - } - - override fun fromLog(table: LogTable) { - rollerVelocity = table.get("Intake Velocity", rollerVelocity) - current = table.get("Intake Current", current) - position = table.get("Intake Roller Position", position) - } - - } - - fun setSpeed(percent: Double) - - fun updateInputs(inputs: Inputs) - - class IntakeIOReal: IntakeIO { - private var motor = - CANSparkFlex( - REVMotorControllerId.IntakeMotor, - CANSparkLowLevel.MotorType.kBrushless - ) - - override fun setSpeed(percent: Double) { - assert(percent in -1.0..1.0) - motor.set(percent) - } - - override fun updateInputs(inputs: Inputs) { - inputs.rollerVelocity = RotationsPerSecond.of(motor.encoder.velocity) - inputs.current = Amps.of(motor.outputCurrent) - inputs.position = Rotations.of(motor.encoder.position.mod(1.0)) - } - } - - class IntakeIOSim: IntakeIO { - - var motor = FlywheelSim( - DCMotor.getNeoVortex(1), - 1.0, - 1.0 - ) - - override fun updateInputs(inputs: Inputs) { - motor.update(Robot.period) - inputs.rollerVelocity = RadiansPerSecond.of(motor.angularVelocityRadPerSec) - inputs.current = Amps.of(motor.currentDrawAmps) - inputs.position += Radians.of(motor.angularVelocityRadPerSec * Robot.period) - inputs.position = Radians.of(inputs.position.`in`(Radians).mod(TAU)) - } - - override fun setSpeed(percent: Double) { - assert(percent in -1.0..1.0) - motor.setInputVoltage(percent * 12) - } - } -} \ No newline at end of file diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/wrist/Wrist.kt b/src/main/java/com/frcteam3636/frc2024/subsystems/wrist/Wrist.kt deleted file mode 100644 index f5c6584..0000000 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/wrist/Wrist.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.frcteam3636.frc2024.subsystems.wrist - -import com.frcteam3636.frc2024.subsystems.arm.Arm -import edu.wpi.first.wpilibj2.command.Subsystem -import org.littletonrobotics.junction.Logger - -object Wrist: Subsystem { - private var io: WristIO = WristIO.WristIOKraken() - - var inputs = WristIO.Inputs() - - override fun periodic() { - Logger.processInputs("Wrist", inputs) - //the wrist should always be parallel to the ground - io.pivotToAndStop(Arm.inputs.position * -1.0) //use position variable from arm - } -} \ No newline at end of file diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/wrist/WristIO.kt b/src/main/java/com/frcteam3636/frc2024/subsystems/wrist/WristIO.kt deleted file mode 100644 index d9f35fe..0000000 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/wrist/WristIO.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.frcteam3636.frc2024.subsystems.wrist - -import com.ctre.phoenix6.configs.TalonFXConfiguration -import com.ctre.phoenix6.controls.MotionMagicTorqueCurrentFOC -import com.ctre.phoenix6.signals.GravityTypeValue -import com.ctre.phoenix6.signals.InvertedValue -import com.ctre.phoenix6.signals.NeutralModeValue -import com.frcteam3636.frc2024.CTREMotorControllerId -import com.frcteam3636.frc2024.TalonFX -import com.frcteam3636.frc2024.utils.math.MotorFFGains -import com.frcteam3636.frc2024.utils.math.PIDGains -import com.frcteam3636.frc2024.utils.math.motorFFGains -import com.frcteam3636.frc2024.utils.math.pidGains -import edu.wpi.first.units.Angle -import edu.wpi.first.units.Measure -import edu.wpi.first.units.Units.* -import edu.wpi.first.wpilibj.DigitalInput -import edu.wpi.first.wpilibj.DutyCycleEncoder -import org.littletonrobotics.junction.LogTable -import org.littletonrobotics.junction.Logger -import org.littletonrobotics.junction.inputs.LoggableInputs - -interface WristIO { - class Inputs : LoggableInputs { - var position = Radians.zero()!! - var velocity = RadiansPerSecond.zero()!! - var voltage = Volts.zero()!! - - override fun toLog(table: LogTable) { - table.put("Position", position) - table.put("Velocity", velocity) - table.put("Voltage", voltage) - } - - override fun fromLog(table: LogTable) { - position = table.get("Position", position) - velocity = table.get("Velocity", velocity) - voltage = table.get("Voltage", voltage) - } - } - fun updateInputs(inputs: Inputs) - - fun pivotToAndStop(position: Measure) - - class WristIOKraken: WristIO { - private val wristMotor = TalonFX(CTREMotorControllerId.WristMotor) - - private val absoluteEncoder = DutyCycleEncoder(DigitalInput(7)) - - init { - val config = TalonFXConfiguration().apply { - MotorOutput.apply { - NeutralMode = NeutralModeValue.Brake - } - - Feedback.apply { - SensorToMechanismRatio = GEAR_RATIO - FeedbackRotorOffset = 0.0 - } - - Slot0.apply { - pidGains = PID_GAINS - motorFFGains = FF_GAINS - GravityType = GravityTypeValue.Arm_Cosine - kG = GRAVITY_GAIN - } - - MotionMagic.apply { - MotionMagicCruiseVelocity = PROFILE_VELOCITY - MotionMagicAcceleration = PROFILE_ACCELERATION - MotionMagicJerk = PROFILE_JERK - } - } - - config.MotorOutput.Inverted = InvertedValue.CounterClockwise_Positive - wristMotor.configurator.apply( - config - ) - } - - override fun updateInputs(inputs: Inputs) { - inputs.position = Rotations.of(wristMotor.position.value) - inputs.velocity = RotationsPerSecond.of(wristMotor.velocity.value) - inputs.voltage = Volts.of(wristMotor.motorVoltage.value) - } - - override fun pivotToAndStop(position: Measure) { - Logger.recordOutput("Wrist/Position Setpoint", position) - - val wristControl = MotionMagicTorqueCurrentFOC(0.0).apply { - Slot = 0 - Position = position.`in`(Rotations) - } - wristMotor.setControl(wristControl) - } - - internal companion object Constants { - private const val GEAR_RATIO = 0.0 - val PID_GAINS = PIDGains(120.0, 0.0, 100.0) //placeholders - val FF_GAINS = MotorFFGains(7.8, 0.0, 0.0) //placeholders - private const val GRAVITY_GAIN = 0.0 - private const val PROFILE_ACCELERATION = 0.0 - private const val PROFILE_JERK = 0.0 - private const val PROFILE_VELOCITY = 0.0 - } - } -} \ No newline at end of file diff --git a/src/main/java/com/frcteam3636/frc2024/CAN.kt b/src/main/kotlin/com/frcteam3636/frc2024/CAN.kt similarity index 97% rename from src/main/java/com/frcteam3636/frc2024/CAN.kt rename to src/main/kotlin/com/frcteam3636/frc2024/CAN.kt index ae119af..91f027b 100644 --- a/src/main/java/com/frcteam3636/frc2024/CAN.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/CAN.kt @@ -36,7 +36,6 @@ enum class CTREMotorControllerId(val num: Int, val bus: String) { FrontRightDrivingMotor(4, "*"), RightArmMotor(10, "*"), LeftArmMotor(11, "*"), - WristMotor(12, "*"), } fun TalonFX(id: CTREMotorControllerId) = TalonFX(id.num, id.bus) \ No newline at end of file diff --git a/src/main/java/com/frcteam3636/frc2024/Dashboard.kt b/src/main/kotlin/com/frcteam3636/frc2024/Dashboard.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/Dashboard.kt rename to src/main/kotlin/com/frcteam3636/frc2024/Dashboard.kt diff --git a/src/main/java/com/frcteam3636/frc2024/Diagnostics.kt b/src/main/kotlin/com/frcteam3636/frc2024/Diagnostics.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/Diagnostics.kt rename to src/main/kotlin/com/frcteam3636/frc2024/Diagnostics.kt diff --git a/src/main/java/com/frcteam3636/frc2024/Main.kt b/src/main/kotlin/com/frcteam3636/frc2024/Main.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/Main.kt rename to src/main/kotlin/com/frcteam3636/frc2024/Main.kt diff --git a/src/main/java/com/frcteam3636/frc2024/Robot.kt b/src/main/kotlin/com/frcteam3636/frc2024/Robot.kt similarity index 95% rename from src/main/java/com/frcteam3636/frc2024/Robot.kt rename to src/main/kotlin/com/frcteam3636/frc2024/Robot.kt index 656c507..bcd5594 100644 --- a/src/main/java/com/frcteam3636/frc2024/Robot.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/Robot.kt @@ -1,13 +1,15 @@ package com.frcteam3636.frc2024 -import BuildConstants import com.ctre.phoenix6.SignalLogger import com.ctre.phoenix6.StatusSignal import com.frcteam3636.frc2024.subsystems.arm.Arm import com.frcteam3636.frc2024.subsystems.drivetrain.Drivetrain import com.frcteam3636.frc2024.subsystems.indexer.Indexer import com.frcteam3636.frc2024.subsystems.intake.Intake -import com.frcteam3636.frc2024.subsystems.wrist.Wrist +import com.frcteam3636.version.BUILD_DATE +import com.frcteam3636.version.DIRTY +import com.frcteam3636.version.GIT_BRANCH +import com.frcteam3636.version.GIT_SHA import edu.wpi.first.hal.FRCNetComm.tInstances import edu.wpi.first.hal.FRCNetComm.tResourceType import edu.wpi.first.hal.HAL @@ -75,11 +77,11 @@ object Robot : LoggedRobot() { /** Start logging or pull replay logs from a file */ private fun configureAdvantageKit() { - Logger.recordMetadata("Git SHA", BuildConstants.GIT_SHA) - Logger.recordMetadata("BuildDate", BuildConstants.BUILD_DATE) - Logger.recordMetadata("Git Tree Dirty", (BuildConstants.DIRTY == 1).toString()) + Logger.recordMetadata("Git SHA", GIT_SHA) + Logger.recordMetadata("Build Date", BUILD_DATE) + Logger.recordMetadata("Git Tree Dirty", (DIRTY == 1).toString()) + Logger.recordMetadata("Git Branch", GIT_BRANCH) Logger.recordMetadata("Model", model.name) - Logger.recordMetadata("Git Branch", BuildConstants.GIT_BRANCH) if (isReal()) { Logger.addDataReceiver(WPILOGWriter()) // Log to a USB stick @@ -122,7 +124,6 @@ object Robot : LoggedRobot() { Drivetrain.register() Indexer.register() Intake.register() - Wrist.register() } /** Expose commands for autonomous routines to use and display an auto picker in Shuffleboard. */ diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/arm/Arm.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/arm/Arm.kt similarity index 83% rename from src/main/java/com/frcteam3636/frc2024/subsystems/arm/Arm.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/arm/Arm.kt index 558330c..1c5f517 100644 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/arm/Arm.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/arm/Arm.kt @@ -2,13 +2,11 @@ package com.frcteam3636.frc2024.subsystems.arm import com.ctre.phoenix6.SignalLogger import com.frcteam3636.frc2024.Robot -import com.frcteam3636.frc2024.subsystems.indexer.IndexerIOPrototype -import com.frcteam3636.frc2024.subsystems.indexer.IndexerIOReal -import com.frcteam3636.frc2024.subsystems.indexer.IndexerIOSim import edu.wpi.first.units.Angle import edu.wpi.first.units.Measure import edu.wpi.first.units.Units.Degrees import edu.wpi.first.units.Units.Volts +import edu.wpi.first.wpilibj.Timer import edu.wpi.first.wpilibj2.command.Subsystem import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine.Direction @@ -16,6 +14,8 @@ import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine.Mechanism import org.littletonrobotics.junction.Logger +private const val SECONDS_BETWEEN_ARM_UPDATES = 0.5 + object Arm : Subsystem { private var io: ArmIO = when (Robot.model) { Robot.Model.SIMULATION -> ArmIOSim() @@ -34,10 +34,17 @@ object Arm : Subsystem { Mechanism(io::setVoltage, null, this) ) + private var timer = Timer().apply { + start() + } + override fun periodic() { io.updateInputs(inputs) - Logger.processInputs("/Arm", inputs) + if (timer.advanceIfElapsed(SECONDS_BETWEEN_ARM_UPDATES) && inputs.absoluteEncoderConnected){ + io.updatePosition(inputs.absoluteEncoderPosition) + } + } fun moveToPosition(position: Position) = diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/arm/ArmIO.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/arm/ArmIO.kt similarity index 93% rename from src/main/java/com/frcteam3636/frc2024/subsystems/arm/ArmIO.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/arm/ArmIO.kt index 9ff9b48..3c5910d 100644 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/arm/ArmIO.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/arm/ArmIO.kt @@ -16,7 +16,6 @@ import edu.wpi.first.units.Units.* import edu.wpi.first.units.Voltage import edu.wpi.first.wpilibj.DigitalInput import edu.wpi.first.wpilibj.DutyCycleEncoder -import edu.wpi.first.wpilibj.simulation.FlywheelSim import edu.wpi.first.wpilibj.simulation.SingleJointedArmSim import org.littletonrobotics.junction.LogTable import org.littletonrobotics.junction.Logger @@ -72,9 +71,12 @@ interface ArmIO{ fun pivotToPosition(position: Measure) - fun setVoltage(volts: Measure) + fun setVoltage(volts: Measure) + + fun updatePosition(position: Measure) } + class ArmIOReal: ArmIO{ private val leftMotor = TalonFX(CTREMotorControllerId.LeftArmMotor) @@ -102,6 +104,11 @@ interface ArmIO{ rightMotor.setPosition(inputs.absoluteEncoderPosition.`in`(Rotations)) } + override fun updatePosition(position: Measure) { + leftMotor.setPosition(position.`in`(Rotations)) + rightMotor.setPosition(position.`in`(Rotations)) + } + override fun pivotToPosition(position: Measure) { Logger.recordOutput("Shooter/Pivot/Position Setpoint", position) @@ -198,6 +205,10 @@ interface ArmIO{ override fun setVoltage(volts: Measure) { armSim.setInputVoltage(volts.`in`(Volts)) } + + override fun updatePosition(position: Measure) { + // no drifting in sim so no need to update + } } class ArmIOPrototype: ArmIO { @@ -210,4 +221,7 @@ interface ArmIO{ override fun setVoltage(volts: Measure) { } + + override fun updatePosition(position: Measure) { + } } \ No newline at end of file diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/AbsolutePose.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/AbsolutePose.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/AbsolutePose.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/AbsolutePose.kt diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/Drivetrain.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/Drivetrain.kt similarity index 99% rename from src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/Drivetrain.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/Drivetrain.kt index 738bad4..f7e2bac 100644 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/Drivetrain.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/Drivetrain.kt @@ -51,7 +51,7 @@ object Drivetrain : Subsystem, Sendable { Robot.Model.COMPETITION -> DrivetrainIOReal.fromKrakenSwerve() Robot.Model.PROTOTYPE -> DrivetrainIOReal.fromNeoSwerve() } - val inputs = DrivetrainIO.Inputs() + val inputs = LoggedDrivetrainInputs() private val absolutePoseIOs = mapOf( "Limelight" to LimelightPoseIOReal( diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/DrivetrainIO.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/DrivetrainIO.kt similarity index 65% rename from src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/DrivetrainIO.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/DrivetrainIO.kt index 8757890..88d9d77 100644 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/DrivetrainIO.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/DrivetrainIO.kt @@ -5,42 +5,23 @@ import com.kauailabs.navx.frc.AHRS import edu.wpi.first.math.geometry.Rotation3d import edu.wpi.first.math.kinematics.SwerveModulePosition import edu.wpi.first.math.kinematics.SwerveModuleState -import org.littletonrobotics.junction.LogTable -import org.littletonrobotics.junction.inputs.LoggableInputs +import org.team9432.annotation.Logged + +@Logged +open class DrivetrainInputs { + var gyroRotation = Rotation3d() + var measuredStates = PerCorner.generate { SwerveModuleState() } + var measuredPositions = PerCorner.generate { SwerveModulePosition() } + var gyroConnected = true +} + abstract class DrivetrainIO { protected abstract val gyro: Gyro abstract val modules: PerCorner - class Inputs : LoggableInputs { - var gyroRotation = Rotation3d() - var measuredStates = PerCorner.generate { SwerveModuleState() } - var measuredPositions = PerCorner.generate { SwerveModulePosition() } - - var gyroConnected = true - - override fun fromLog(table: LogTable?) { - gyroRotation = table?.get("Gyro Rotation", gyroRotation)!![0] - measuredStates = - PerCorner.fromConventionalArray( - table.get("Measured States", *measuredStates.toTypedArray()) - ) - measuredPositions = - PerCorner.fromConventionalArray( - table.get("Measured Positions", *measuredPositions.toTypedArray()) - ) - gyroConnected = table.get("Gyro Connected", false) - } - - override fun toLog(table: LogTable?) { - table?.put("Gyro Rotation", gyroRotation) - table?.put("Measured States", *measuredStates.toTypedArray()) - table?.put("Measured Positions", *measuredPositions.toTypedArray()) - table?.put("Gyro Connected", gyroConnected) - } - } - fun updateInputs(inputs: Inputs) { + fun updateInputs(inputs: DrivetrainInputs) { gyro.periodic() modules.forEach(SwerveModule::periodic) diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/Gyro.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/Gyro.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/Gyro.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/Gyro.kt diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/LocalADStarAK.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/LocalADStarAK.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/LocalADStarAK.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/LocalADStarAK.kt diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/Module.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/Module.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/Module.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/Module.kt diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/RemoteADStarAK.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/RemoteADStarAK.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/subsystems/drivetrain/RemoteADStarAK.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/drivetrain/RemoteADStarAK.kt diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/indexer/Indexer.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/indexer/Indexer.kt similarity index 98% rename from src/main/java/com/frcteam3636/frc2024/subsystems/indexer/Indexer.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/indexer/Indexer.kt index 8675494..9ed00d9 100644 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/indexer/Indexer.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/indexer/Indexer.kt @@ -17,7 +17,7 @@ object Indexer: Subsystem { Robot.Model.PROTOTYPE -> IndexerIOPrototype() } - var inputs = IndexerIO.Inputs() + var inputs = LoggedIndexerInputs() override fun periodic() { io.updateInputs(inputs) diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/indexer/IndexerIO.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/indexer/IndexerIO.kt similarity index 69% rename from src/main/java/com/frcteam3636/frc2024/subsystems/indexer/IndexerIO.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/indexer/IndexerIO.kt index 4ddac6f..f5c2f2d 100644 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/indexer/IndexerIO.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/indexer/IndexerIO.kt @@ -11,6 +11,7 @@ import com.revrobotics.CANSparkLowLevel import edu.wpi.first.math.system.plant.DCMotor import edu.wpi.first.units.Units.* import edu.wpi.first.wpilibj.simulation.FlywheelSim +import org.team9432.annotation.Logged enum class BalloonState { Blue, @@ -18,28 +19,16 @@ enum class BalloonState { None } -interface IndexerIO { - class Inputs : LoggableInputs { - var indexerVelocity = RotationsPerSecond.zero() - var indexerCurrent = Amps.zero() - var balloonState: BalloonState = BalloonState.None - var position = Radians.zero() - - override fun toLog(table: LogTable?) { - table?.put("Indexer Wheel Velocity", indexerVelocity) - table?.put("Indexer Wheel Current", indexerCurrent) - table?.put("Balloon Color", balloonState) - table?.put("Indexer Wheel Angle", position) - } +@Logged +open class IndexerInputs { + var indexerVelocity = RotationsPerSecond.zero()!! + var indexerCurrent = Amps.zero()!! + var balloonState: BalloonState = BalloonState.None + var position = Radians.zero()!! +} - override fun fromLog(table: LogTable) { - indexerVelocity = table.get("Indexer Velocity", indexerVelocity) - indexerCurrent = table.get("Indexer Wheel Current", indexerCurrent) - balloonState = table.get("Balloon Color", balloonState) - position = table.get("Indexer Wheel Angle", position) - } - } - fun updateInputs(inputs: Inputs) +interface IndexerIO { + fun updateInputs(inputs: IndexerInputs) fun setSpinSpeed(speed: Double) // percent of full speed @@ -58,7 +47,7 @@ class IndexerIOReal : IndexerIO{ CANSparkLowLevel.MotorType.kBrushless ) - override fun updateInputs(inputs: IndexerIO.Inputs) { + override fun updateInputs(inputs: IndexerInputs) { inputs.indexerVelocity = Rotations.per(Minute).of(indexerMotor.encoder.velocity) inputs.indexerCurrent = Amps.of(indexerMotor.outputCurrent) inputs.position = Rotations.of(indexerMotor.encoder.position) @@ -84,7 +73,7 @@ class IndexerIOSim: IndexerIO { 1.0 ) - override fun updateInputs(inputs: IndexerIO.Inputs) { + override fun updateInputs(inputs: IndexerInputs) { flywheelSim.update(Robot.period) inputs.indexerVelocity = RadiansPerSecond.of(flywheelSim.angularVelocityRadPerSec) inputs.position += Radians.of(flywheelSim.angularVelocityRadPerSec * Robot.period) @@ -98,7 +87,7 @@ class IndexerIOSim: IndexerIO { } class IndexerIOPrototype: IndexerIO { - override fun updateInputs(inputs: IndexerIO.Inputs) { + override fun updateInputs(inputs: IndexerInputs) { } override fun setSpinSpeed(speed: Double) { diff --git a/src/main/java/com/frcteam3636/frc2024/subsystems/intake/Intake.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/intake/Intake.kt similarity index 88% rename from src/main/java/com/frcteam3636/frc2024/subsystems/intake/Intake.kt rename to src/main/kotlin/com/frcteam3636/frc2024/subsystems/intake/Intake.kt index 2cad191..4ff8b0b 100644 --- a/src/main/java/com/frcteam3636/frc2024/subsystems/intake/Intake.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/intake/Intake.kt @@ -12,12 +12,12 @@ import org.littletonrobotics.junction.Logger object Intake: Subsystem { private var io: IntakeIO = when (Robot.model) { - Robot.Model.SIMULATION -> IntakeIO.IntakeIOSim() - Robot.Model.COMPETITION -> IntakeIO.IntakeIOReal() - Robot.Model.PROTOTYPE -> IntakeIO.IntakeIOSim() + Robot.Model.SIMULATION -> IntakeIOSim() + Robot.Model.COMPETITION -> IntakeIOReal() + Robot.Model.PROTOTYPE -> IntakeIOSim() } - var inputs = IntakeIO.Inputs() + var inputs = LoggedIntakeInputs() var mechanism = Mechanism2d(100.0, 200.0) var intakeAngleLigament = MechanismLigament2d("Intake Ligament", 50.0, 90.0, 5.0, Color8Bit(Color.kGreen)) diff --git a/src/main/kotlin/com/frcteam3636/frc2024/subsystems/intake/IntakeIO.kt b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/intake/IntakeIO.kt new file mode 100644 index 0000000..6b749c9 --- /dev/null +++ b/src/main/kotlin/com/frcteam3636/frc2024/subsystems/intake/IntakeIO.kt @@ -0,0 +1,65 @@ +package com.frcteam3636.frc2024.subsystems.intake +import com.frcteam3636.frc2024.CANSparkFlex +import com.frcteam3636.frc2024.REVMotorControllerId +import com.frcteam3636.frc2024.Robot +import com.frcteam3636.frc2024.utils.math.TAU +import com.revrobotics.CANSparkLowLevel +import edu.wpi.first.math.system.plant.DCMotor +import edu.wpi.first.units.Units.* +import edu.wpi.first.wpilibj.simulation.FlywheelSim +import org.littletonrobotics.junction.AutoLog +import org.littletonrobotics.junction.LogTable +import org.littletonrobotics.junction.inputs.LoggableInputs +import org.team9432.annotation.Logged + +@Logged +open class IntakeInputs { + var rollerVelocity = RotationsPerSecond.zero()!! + var current = Amps.zero()!! + var position = Radians.zero()!! +} + +interface IntakeIO { + fun setSpeed(percent: Double) + fun updateInputs(inputs: IntakeInputs) +} + +class IntakeIOReal: IntakeIO { + private var motor = + CANSparkFlex( + REVMotorControllerId.IntakeMotor, + CANSparkLowLevel.MotorType.kBrushless + ) + + override fun setSpeed(percent: Double) { + assert(percent in -1.0..1.0) + motor.set(percent) + } + + override fun updateInputs(inputs: IntakeInputs) { + inputs.rollerVelocity = RotationsPerSecond.of(motor.encoder.velocity) + inputs.current = Amps.of(motor.outputCurrent) + inputs.position = Rotations.of(motor.encoder.position.mod(1.0)) + } +} + +class IntakeIOSim: IntakeIO { + var motor = FlywheelSim( + DCMotor.getNeoVortex(1), + 1.0, + 1.0 + ) + + override fun updateInputs(inputs: IntakeInputs) { + motor.update(Robot.period) + inputs.rollerVelocity = RadiansPerSecond.of(motor.angularVelocityRadPerSec) + inputs.current = Amps.of(motor.currentDrawAmps) + inputs.position += Radians.of(motor.angularVelocityRadPerSec * Robot.period) + inputs.position = Radians.of(inputs.position.`in`(Radians).mod(TAU)) + } + + override fun setSpeed(percent: Double) { + assert(percent in -1.0..1.0) + motor.setInputVoltage(percent * 12) + } +} \ No newline at end of file diff --git a/src/main/java/com/frcteam3636/frc2024/utils/Elastic.kt b/src/main/kotlin/com/frcteam3636/frc2024/utils/Elastic.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/utils/Elastic.kt rename to src/main/kotlin/com/frcteam3636/frc2024/utils/Elastic.kt diff --git a/src/main/java/com/frcteam3636/frc2024/utils/Inputs.kt b/src/main/kotlin/com/frcteam3636/frc2024/utils/Inputs.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/utils/Inputs.kt rename to src/main/kotlin/com/frcteam3636/frc2024/utils/Inputs.kt diff --git a/src/main/java/com/frcteam3636/frc2024/utils/LimelightHelpers.kt b/src/main/kotlin/com/frcteam3636/frc2024/utils/LimelightHelpers.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/utils/LimelightHelpers.kt rename to src/main/kotlin/com/frcteam3636/frc2024/utils/LimelightHelpers.kt diff --git a/src/main/kotlin/com/frcteam3636/frc2024/utils/LogTableUtils.kt b/src/main/kotlin/com/frcteam3636/frc2024/utils/LogTableUtils.kt new file mode 100644 index 0000000..b6d3831 --- /dev/null +++ b/src/main/kotlin/com/frcteam3636/frc2024/utils/LogTableUtils.kt @@ -0,0 +1,11 @@ +package com.frcteam3636.frc2024.utils + +import com.frcteam3636.frc2024.utils.swerve.PerCorner +import edu.wpi.first.util.struct.StructSerializable +import org.littletonrobotics.junction.LogTable + +object LogTableUtils { + inline fun LogTable.kPut(key: String, value: PerCorner) = put(key, *value.toTypedArray()) + inline fun LogTable.kGet(key: String, defaultValue: PerCorner) + = PerCorner.fromConventionalArray(get(key, *defaultValue.toTypedArray())) +} \ No newline at end of file diff --git a/src/main/java/com/frcteam3636/frc2024/utils/math/Control.kt b/src/main/kotlin/com/frcteam3636/frc2024/utils/math/Control.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/utils/math/Control.kt rename to src/main/kotlin/com/frcteam3636/frc2024/utils/math/Control.kt diff --git a/src/main/java/com/frcteam3636/frc2024/utils/math/Math.kt b/src/main/kotlin/com/frcteam3636/frc2024/utils/math/Math.kt similarity index 100% rename from src/main/java/com/frcteam3636/frc2024/utils/math/Math.kt rename to src/main/kotlin/com/frcteam3636/frc2024/utils/math/Math.kt diff --git a/src/main/java/com/frcteam3636/frc2024/utils/swerve/Swerve.kt b/src/main/kotlin/com/frcteam3636/frc2024/utils/swerve/Swerve.kt similarity index 97% rename from src/main/java/com/frcteam3636/frc2024/utils/swerve/Swerve.kt rename to src/main/kotlin/com/frcteam3636/frc2024/utils/swerve/Swerve.kt index 31bc026..3491087 100644 --- a/src/main/java/com/frcteam3636/frc2024/utils/swerve/Swerve.kt +++ b/src/main/kotlin/com/frcteam3636/frc2024/utils/swerve/Swerve.kt @@ -55,7 +55,7 @@ data class PerCorner(val frontLeft: T, val backLeft: T, val backRight: T, val frontRight = block(DrivetrainCorner.FRONT_RIGHT), ) - internal fun fromConventionalArray(array: Array): PerCorner = + fun fromConventionalArray(array: Array): PerCorner = PerCorner( frontLeft = array[0], backLeft = array[1], diff --git a/vendordeps/AdvantageKit.json b/vendordeps/AdvantageKit.json index a3a16b6..57394b3 100644 --- a/vendordeps/AdvantageKit.json +++ b/vendordeps/AdvantageKit.json @@ -1,7 +1,7 @@ { "fileName": "AdvantageKit.json", "name": "AdvantageKit", - "version": "3.0.0", + "version": "3.2.1", "uuid": "d820cc26-74e3-11ec-90d6-0242ac120003", "frcYear": "2024", "mavenUrls": [], @@ -10,24 +10,24 @@ { "groupId": "org.littletonrobotics.akit.junction", "artifactId": "wpilib-shim", - "version": "3.0.0" + "version": "3.2.1" }, { "groupId": "org.littletonrobotics.akit.junction", "artifactId": "junction-core", - "version": "3.0.0" + "version": "3.2.1" }, { "groupId": "org.littletonrobotics.akit.conduit", "artifactId": "conduit-api", - "version": "3.0.0" + "version": "3.2.1" } ], "jniDependencies": [ { "groupId": "org.littletonrobotics.akit.conduit", "artifactId": "conduit-wpilibio", - "version": "3.0.0", + "version": "3.2.1", "skipInvalidPlatforms": false, "isJar": false, "validPlatforms": [ @@ -39,4 +39,4 @@ } ], "cppDependencies": [] -} +} \ No newline at end of file