From 98326b3c90a0c1e24cba2d76d2207eaa20f5a07a Mon Sep 17 00:00:00 2001 From: Kevin Cooney Date: Sun, 8 Feb 2026 08:55:35 -0800 Subject: [PATCH] Add vendor-ctre project --- .../groovy/java-common-conventions.gradle | 4 +- .../main/groovy/publishing-conventions.gradle | 10 +++- .../team2813/lib2813/control/InvertType.java | 42 +++------------ .../team2813/lib2813/util/ConfigUtils.java | 13 ----- .../lib2813/control/InvertTypeTest.java | 21 +------- settings.gradle | 6 +-- vendor/ctre/build.gradle | 45 ++++++++++++++++ .../vendor/ctre}/DeviceInformation.java | 2 +- .../lib2813/vendor/ctre/InvertTypes.java | 51 +++++++++++++++++++ .../lib2813/vendor/ctre/PhoenixUtils.java | 40 +++++++++++++++ .../vendor/ctre/encoder}/CancoderWrapper.java | 8 +-- .../vendor/ctre}/imu/Pigeon2Wrapper.java | 8 +-- .../vendor/ctre/motor}/TalonFXWrapper.java | 38 +++++++------- .../lib2813/vendor/ctre/InvertTypesTest.java | 49 ++++++++++++++++++ .../vendor/ctre/motor}/TalonFXEqualsTest.java | 4 +- {lib => vendor/ctre}/vendordeps/Phoenix6.json | 0 16 files changed, 236 insertions(+), 105 deletions(-) create mode 100644 vendor/ctre/build.gradle rename {lib/src/main/java/com/team2813/lib2813/control => vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre}/DeviceInformation.java (98%) create mode 100644 vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/InvertTypes.java create mode 100644 vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/PhoenixUtils.java rename {lib/src/main/java/com/team2813/lib2813/control/encoders => vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/encoder}/CancoderWrapper.java (92%) rename {lib/src/main/java/com/team2813/lib2813/control => vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre}/imu/Pigeon2Wrapper.java (92%) rename {lib/src/main/java/com/team2813/lib2813/control/motors => vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/motor}/TalonFXWrapper.java (90%) create mode 100644 vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/InvertTypesTest.java rename {lib/src/test/java/com/team2813/lib2813/control/motors => vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/motor}/TalonFXEqualsTest.java (89%) rename {lib => vendor/ctre}/vendordeps/Phoenix6.json (100%) diff --git a/buildSrc/src/main/groovy/java-common-conventions.gradle b/buildSrc/src/main/groovy/java-common-conventions.gradle index 4ec7486e..56a308b8 100644 --- a/buildSrc/src/main/groovy/java-common-conventions.gradle +++ b/buildSrc/src/main/groovy/java-common-conventions.gradle @@ -95,7 +95,7 @@ spotless { endWithNewline() } groovyGradle { - greclipse().configFile('../greclipse-gradle.properties') + greclipse().configFile("$rootDir/greclipse-gradle.properties") } java { importOrder() // Use the default importOrder configuration (can override) @@ -107,7 +107,7 @@ spotless { formatAnnotations() // fix formatting of type annotations - licenseHeaderFile("../java-copyright-header.txt") + licenseHeaderFile("$rootDir/java-copyright-header.txt") } } diff --git a/buildSrc/src/main/groovy/publishing-conventions.gradle b/buildSrc/src/main/groovy/publishing-conventions.gradle index f724de96..f3b4c0b5 100644 --- a/buildSrc/src/main/groovy/publishing-conventions.gradle +++ b/buildSrc/src/main/groovy/publishing-conventions.gradle @@ -2,15 +2,21 @@ plugins { id 'com.vanniktech.maven.publish' } -version = '2.0.0-rc-2' +group = 'com.team2813.lib2813' +version = "2.0.0-rc-3" mavenPublishing { + publishToMavenCentral() if (gradle.startParameter.taskNames.any { it.contains('MavenCentral') }) { signAllPublications() } - coordinates('com.team2813.lib2813', project.name, project.version) + coordinates( + group, + // The below evaluates to "vendor-ctre" for "vendor/ctre" + project.path.replace(':', '-').substring(1), + version) pom { inceptionYear = '2023' diff --git a/lib/src/main/java/com/team2813/lib2813/control/InvertType.java b/lib/src/main/java/com/team2813/lib2813/control/InvertType.java index eaf935c6..ca6d398b 100644 --- a/lib/src/main/java/com/team2813/lib2813/control/InvertType.java +++ b/lib/src/main/java/com/team2813/lib2813/control/InvertType.java @@ -1,5 +1,5 @@ /* -Copyright 2024-2025 Prospect Robotics SWENext Club +Copyright 2024-2026 Prospect Robotics SWENext Club Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,13 +17,12 @@ import static java.util.stream.Collectors.toUnmodifiableMap; -import com.ctre.phoenix6.signals.InvertedValue; import java.util.*; import java.util.stream.Stream; public enum InvertType { - CLOCKWISE(InvertedValue.Clockwise_Positive, true), - COUNTER_CLOCKWISE(InvertedValue.CounterClockwise_Positive, false), + CLOCKWISE(true), + COUNTER_CLOCKWISE(false), FOLLOW_MASTER, OPPOSE_MASTER; @@ -34,34 +33,20 @@ public enum InvertType { public static final Set rotationValues = Collections.unmodifiableSet(EnumSet.of(CLOCKWISE, COUNTER_CLOCKWISE)); - private final Optional phoenixInvert; private final Optional sparkMaxInvert; InvertType() { - phoenixInvert = Optional.empty(); sparkMaxInvert = Optional.empty(); } - InvertType(InvertedValue phoenixInvert, boolean sparkMaxInvert) { - this.phoenixInvert = Optional.of(phoenixInvert); + InvertType(boolean sparkMaxInvert) { this.sparkMaxInvert = Optional.of(sparkMaxInvert); } - /** - * Gets an {@link InvertType} from a phoenix {@link InvertedValue}. - * - * @param v the {@link InvertedValue} to search for - * @return {@link Optional#empty()} if no {@link InvertType} is found, otherwise, an optional - * describing the {@link InvertType} - */ - public static Optional fromPhoenixInvert(InvertedValue v) { - return Optional.of(Maps.phoenixMap.get(v)); - } - /** * Gets an {@link InvertType} from a spark max invert * - * @param v the {@link InvertedValue} to search for + * @param v the value to search for * @return {@link Optional#empty()} if no {@link InvertType} is found, otherwise, an optional * describing the {@link InvertType} */ @@ -69,14 +54,6 @@ public static Optional fromSparkMaxInvert(boolean v) { return Optional.of(Maps.sparkMaxMap.get(v)); } - public Optional phoenixInvert() { - return phoenixInvert; - } - - private InvertedValue forcePhoenixInvert() { - return phoenixInvert.orElseThrow(); - } - public Optional sparkMaxInvert() { return sparkMaxInvert; } @@ -86,15 +63,10 @@ private boolean forceSparkMaxInvert() { } /** - * Contains the maps for {@link InvertType#fromPhoenixInvert(InvertedValue)} and {@link - * InvertType#fromSparkMaxInvert(boolean)}. In a static class so that they will only be - * initialized if they are needed. + * Contains the maps for {@link InvertType#fromSparkMaxInvert(boolean)}. In a static class so that + * they will only be initialized if they are needed. */ private static final class Maps { - private static final Map phoenixMap = - Stream.of(InvertType.values()) - .filter((j) -> j.phoenixInvert.isPresent()) - .collect(toUnmodifiableMap(InvertType::forcePhoenixInvert, (j) -> j, (a, b) -> null)); private static final Map sparkMaxMap = Stream.of(InvertType.values()) .filter((j) -> j.sparkMaxInvert.isPresent()) diff --git a/lib/src/main/java/com/team2813/lib2813/util/ConfigUtils.java b/lib/src/main/java/com/team2813/lib2813/util/ConfigUtils.java index 4f14d843..2e5e750d 100644 --- a/lib/src/main/java/com/team2813/lib2813/util/ConfigUtils.java +++ b/lib/src/main/java/com/team2813/lib2813/util/ConfigUtils.java @@ -15,7 +15,6 @@ */ package com.team2813.lib2813.util; -import com.ctre.phoenix6.StatusCode; import com.revrobotics.REVLibError; import edu.wpi.first.wpilibj.DriverStation; import java.util.function.Supplier; @@ -39,16 +38,4 @@ public static void revConfig(Supplier configMethod) { DriverStation.reportError(String.format("%s: Config Failed", errorCode.toString()), false); } } - - public static void phoenix6Config(Supplier configMethod) { - StatusCode errorCode = configMethod.get(); - for (int i = 1; i <= ATTEMPTS && errorCode != StatusCode.OK; i++) { - DriverStation.reportError( - String.format("%s: Config Attempt %d Failed", errorCode.toString(), i), false); - errorCode = configMethod.get(); - } - if (errorCode != StatusCode.OK) { - DriverStation.reportError(String.format("%s: Config Failed", errorCode.toString()), false); - } - } } diff --git a/lib/src/test/java/com/team2813/lib2813/control/InvertTypeTest.java b/lib/src/test/java/com/team2813/lib2813/control/InvertTypeTest.java index 618c5e68..5851ad64 100644 --- a/lib/src/test/java/com/team2813/lib2813/control/InvertTypeTest.java +++ b/lib/src/test/java/com/team2813/lib2813/control/InvertTypeTest.java @@ -1,5 +1,5 @@ /* -Copyright 2024-2025 Prospect Robotics SWENext Club +Copyright 2024-2026 Prospect Robotics SWENext Club Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,33 +18,16 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import com.ctre.phoenix6.signals.InvertedValue; import org.junit.Test; public class InvertTypeTest { - @Test - public void phoenixInvertsExist() { - for (InvertType v : InvertType.rotationValues) { - assertTrue( - String.format("No phoenix invert exists for InvertType %s.", v), - v.phoenixInvert().isPresent()); - } - } @Test public void sparkMaxInvertsExist() { for (InvertType v : InvertType.rotationValues) { assertTrue( String.format("No spark max invert exists for InvertType %s.", v), - v.phoenixInvert().isPresent()); - } - } - - @Test - public void fromPhoenixInvertTest() { - for (InvertType v : InvertType.rotationValues) { - InvertedValue val = v.phoenixInvert().orElseThrow(); - assertEquals(v, InvertType.fromPhoenixInvert(val).orElse(null)); + v.sparkMaxInvert().isPresent()); } } diff --git a/settings.gradle b/settings.gradle index 74df31fd..356e580e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,7 +8,5 @@ */ rootProject.name = 'lib2813' -include('lib') -include('limelight') -include('vision') -include('testing') +include 'lib', 'limelight', 'vision', 'testing' +include 'vendor:ctre' diff --git a/vendor/ctre/build.gradle b/vendor/ctre/build.gradle new file mode 100644 index 00000000..ec8780a1 --- /dev/null +++ b/vendor/ctre/build.gradle @@ -0,0 +1,45 @@ +plugins { + id 'java-common-conventions' + id 'publishing-conventions' + id 'edu.wpi.first.GradleRIO' version '2026.1.1' +} + +dependencies { + implementation wpi.java.deps.wpilib() + implementation wpi.java.vendor.java() + implementation project(':lib') + + 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() + + testImplementation(platform('org.junit:junit-bom:5.13.1')) + testImplementation('org.junit.jupiter:junit-jupiter') + testImplementation('com.google.truth:truth:1.4.4') + testRuntimeOnly('org.junit.platform:junit-platform-launcher') +} + +// the magic line that makes tests work :) +wpi.java.configureTestTasks(test) + +tasks.named('test') { + useJUnitPlatform() +} + +mavenPublishing { + pom { + name = '2813 CTRE Vendor Library' + description = 'CTRE extensions to team2813:lib' + developers { + developer { + id = 'cuttestkittensrule' + name = 'Kyle' + email = 'mangoiscute95@gmail.com' + } + } + } +} diff --git a/lib/src/main/java/com/team2813/lib2813/control/DeviceInformation.java b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/DeviceInformation.java similarity index 98% rename from lib/src/main/java/com/team2813/lib2813/control/DeviceInformation.java rename to vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/DeviceInformation.java index e5086076..7b5b0cd0 100644 --- a/lib/src/main/java/com/team2813/lib2813/control/DeviceInformation.java +++ b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/DeviceInformation.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.team2813.lib2813.control; +package com.team2813.lib2813.vendor.ctre; import com.ctre.phoenix6.CANBus; import com.team2813.lib2813.util.InputValidation; diff --git a/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/InvertTypes.java b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/InvertTypes.java new file mode 100644 index 00000000..5ec3f076 --- /dev/null +++ b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/InvertTypes.java @@ -0,0 +1,51 @@ +/* +Copyright 2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.vendor.ctre; + +import com.ctre.phoenix6.signals.InvertedValue; +import com.team2813.lib2813.control.InvertType; +import java.util.Objects; +import java.util.Optional; + +/** Utility methods for working with {@link InvertType} for CTRE devices. */ +public class InvertTypes { + + /** + * Gets the {@link InvertedValue} for the given {@link InvertType} + * + * @return The {@code InvertedValue}, or {@link Optional#empty()} if the provided {@code + * invertType} is not a rotational value. + */ + public static Optional toInvertValue(InvertType invertType) { + return switch (Objects.requireNonNull(invertType, "invertType should not be null")) { + case CLOCKWISE -> Optional.of(InvertedValue.Clockwise_Positive); + case COUNTER_CLOCKWISE -> Optional.of(InvertedValue.CounterClockwise_Positive); + default -> Optional.empty(); + }; + } + + /** Gets the {@link InvertType} for the given {@link InvertedValue} */ + public static InvertType toInvertType(InvertedValue invertedValue) { + return switch (Objects.requireNonNull(invertedValue, "invertedValue should not be null")) { + case Clockwise_Positive -> InvertType.CLOCKWISE; + case CounterClockwise_Positive -> InvertType.COUNTER_CLOCKWISE; + }; + } + + private InvertTypes() { + throw new AssertionError("Not instantiable"); + } +} diff --git a/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/PhoenixUtils.java b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/PhoenixUtils.java new file mode 100644 index 00000000..1a19318f --- /dev/null +++ b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/PhoenixUtils.java @@ -0,0 +1,40 @@ +/* +Copyright 2023-2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.vendor.ctre; + +import com.ctre.phoenix6.StatusCode; +import edu.wpi.first.wpilibj.DriverStation; +import java.util.function.Supplier; + +public class PhoenixUtils { + private static final int ATTEMPTS = 10; + + public static void phoenix6Config(Supplier configMethod) { + StatusCode errorCode = configMethod.get(); + for (int i = 1; i <= ATTEMPTS && errorCode != StatusCode.OK; i++) { + DriverStation.reportError( + String.format("%s: Config Attempt %d Failed", errorCode.toString(), i), false); + errorCode = configMethod.get(); + } + if (errorCode != StatusCode.OK) { + DriverStation.reportError(String.format("%s: Config Failed", errorCode.toString()), false); + } + } + + private PhoenixUtils() { + throw new AssertionError("Not instantiable"); + } +} diff --git a/lib/src/main/java/com/team2813/lib2813/control/encoders/CancoderWrapper.java b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/encoder/CancoderWrapper.java similarity index 92% rename from lib/src/main/java/com/team2813/lib2813/control/encoders/CancoderWrapper.java rename to vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/encoder/CancoderWrapper.java index f47da9df..b71263ec 100644 --- a/lib/src/main/java/com/team2813/lib2813/control/encoders/CancoderWrapper.java +++ b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/encoder/CancoderWrapper.java @@ -13,13 +13,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.team2813.lib2813.control.encoders; +package com.team2813.lib2813.vendor.ctre.encoder; import com.ctre.phoenix6.CANBus; import com.ctre.phoenix6.hardware.CANcoder; -import com.team2813.lib2813.control.DeviceInformation; import com.team2813.lib2813.control.Encoder; -import com.team2813.lib2813.util.ConfigUtils; +import com.team2813.lib2813.vendor.ctre.DeviceInformation; +import com.team2813.lib2813.vendor.ctre.PhoenixUtils; import edu.wpi.first.units.Units; import edu.wpi.first.units.measure.Angle; import edu.wpi.first.units.measure.AngularVelocity; @@ -78,7 +78,7 @@ public Angle getPositionMeasure() { @Override public void setPosition(Angle position) { - ConfigUtils.phoenix6Config(() -> cancoder.setPosition(position.in(Units.Rotations))); + PhoenixUtils.phoenix6Config(() -> cancoder.setPosition(position.in(Units.Rotations))); } public CANcoder encoder() { diff --git a/lib/src/main/java/com/team2813/lib2813/control/imu/Pigeon2Wrapper.java b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/imu/Pigeon2Wrapper.java similarity index 92% rename from lib/src/main/java/com/team2813/lib2813/control/imu/Pigeon2Wrapper.java rename to vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/imu/Pigeon2Wrapper.java index 2aac7823..718eeaa2 100644 --- a/lib/src/main/java/com/team2813/lib2813/control/imu/Pigeon2Wrapper.java +++ b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/imu/Pigeon2Wrapper.java @@ -13,12 +13,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.team2813.lib2813.control.imu; +package com.team2813.lib2813.vendor.ctre.imu; import com.ctre.phoenix6.CANBus; import com.ctre.phoenix6.hardware.Pigeon2; -import com.team2813.lib2813.control.DeviceInformation; -import com.team2813.lib2813.util.ConfigUtils; +import com.team2813.lib2813.vendor.ctre.DeviceInformation; +import com.team2813.lib2813.vendor.ctre.PhoenixUtils; public class Pigeon2Wrapper { private final Pigeon2 pigeon; @@ -74,7 +74,7 @@ public double getHeading() { } public void setHeading(double angle) { - ConfigUtils.phoenix6Config(() -> pigeon.setYaw(angle)); + PhoenixUtils.phoenix6Config(() -> pigeon.setYaw(angle)); currentHeading = angle; } diff --git a/lib/src/main/java/com/team2813/lib2813/control/motors/TalonFXWrapper.java b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/motor/TalonFXWrapper.java similarity index 90% rename from lib/src/main/java/com/team2813/lib2813/control/motors/TalonFXWrapper.java rename to vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/motor/TalonFXWrapper.java index 006e0f9e..62f2cc37 100644 --- a/lib/src/main/java/com/team2813/lib2813/control/motors/TalonFXWrapper.java +++ b/vendor/ctre/src/main/java/com/team2813/lib2813/vendor/ctre/motor/TalonFXWrapper.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.team2813.lib2813.control.motors; +package com.team2813.lib2813.vendor.ctre.motor; import static com.team2813.lib2813.util.InputValidation.checkCanId; @@ -24,14 +24,16 @@ import com.ctre.phoenix6.configs.TalonFXConfigurator; import com.ctre.phoenix6.controls.*; import com.ctre.phoenix6.hardware.TalonFX; +import com.ctre.phoenix6.signals.InvertedValue; import com.ctre.phoenix6.signals.MotorAlignmentValue; import com.ctre.phoenix6.signals.NeutralModeValue; import com.team2813.lib2813.control.ControlMode; -import com.team2813.lib2813.control.DeviceInformation; import com.team2813.lib2813.control.InvertType; import com.team2813.lib2813.control.PIDMotor; import com.team2813.lib2813.subsystems.MotorSubsystem; import com.team2813.lib2813.util.InvalidCanIdException; +import com.team2813.lib2813.vendor.ctre.DeviceInformation; +import com.team2813.lib2813.vendor.ctre.InvertTypes; import edu.wpi.first.units.Units; import edu.wpi.first.units.measure.Angle; import edu.wpi.first.units.measure.AngularVelocity; @@ -63,18 +65,15 @@ public class TalonFXWrapper implements PIDMotor { * @throws InvalidCanIdException if the CAN id is invalid */ public TalonFXWrapper(int canID, CANBus canbus, InvertType invertType) { - Objects.requireNonNull(invertType, "invertType should not be null"); Objects.requireNonNull(canbus, "canbus should not be null"); + InvertedValue invertedValue = toInvertedValue(invertType); if (!InvertType.rotationValues.contains(invertType)) { throw new IllegalArgumentException("invertType invalid"); } motor = new TalonFX(checkCanId(canID), canbus); TalonFXConfiguration config = new TalonFXConfiguration(); - // should never throw anything, as the tests guarantee that everything in - // rotationValues - // returns a non-empty value with phoenixInvert - config.MotorOutput.Inverted = invertType.phoenixInvert().orElseThrow(AssertionError::new); + config.MotorOutput.Inverted = invertedValue; config.CurrentLimits = new CurrentLimitsConfigs().withStatorCurrentLimit(40).withSupplyCurrentLimitEnable(true); TalonFXConfigurator configurator = motor.getConfigurator(); @@ -117,17 +116,11 @@ public TalonFXWrapper(int canID, String canbusName, InvertType invertType) { * @throws InvalidCanIdException if the CAN id is invalid */ public TalonFXWrapper(int canID, InvertType invertType) { - Objects.requireNonNull(invertType, "invertType should not be null"); + InvertedValue invertedValue = toInvertedValue(invertType); motor = new TalonFX(checkCanId(canID)); - if (!InvertType.rotationValues.contains(invertType)) { - throw new IllegalArgumentException("invertType invalid"); - } TalonFXConfiguration config = new TalonFXConfiguration(); - // should never throw anything, as the tests guarantee that everything in - // rotationValues - // returns a non-empty value with phoenixInvert - config.MotorOutput.Inverted = invertType.phoenixInvert().orElseThrow(AssertionError::new); + config.MotorOutput.Inverted = invertedValue; config.CurrentLimits = new CurrentLimitsConfigs().withStatorCurrentLimit(40).withSupplyCurrentLimitEnable(true); TalonFXConfigurator configurator = motor.getConfigurator(); @@ -245,8 +238,7 @@ public void addFollower(int deviceNumber, CANBus canbus, InvertType invertType) Optional alignmentValue = toMotorAlignmentValue(invertType); if (alignmentValue.isEmpty()) { TalonFXConfiguration conf = new TalonFXConfiguration(); - // guaranteed to succeed - conf.MotorOutput.Inverted = invertType.phoenixInvert().orElseThrow(AssertionError::new); + conf.MotorOutput.Inverted = toInvertedValue(invertType); follower.setControl(new StrictFollower(information.id())); } else { follower.setControl(new Follower(information.id(), alignmentValue.get())); @@ -259,8 +251,7 @@ public void addFollower(int deviceNumber, InvertType invertType) { Optional alignmentValue = toMotorAlignmentValue(invertType); if (alignmentValue.isEmpty()) { TalonFXConfiguration conf = new TalonFXConfiguration(); - // guaranteed to succeed - conf.MotorOutput.Inverted = invertType.phoenixInvert().orElseThrow(AssertionError::new); + conf.MotorOutput.Inverted = toInvertedValue(invertType); follower.setControl(new StrictFollower(information.id())); } else { follower.setControl(new Follower(information.id(), alignmentValue.get())); @@ -269,6 +260,7 @@ public void addFollower(int deviceNumber, InvertType invertType) { } private static Optional toMotorAlignmentValue(InvertType invertType) { + Objects.requireNonNull(invertType, "invertType should not be null"); if (InvertType.rotationValues.contains(invertType)) { return Optional.empty(); } @@ -276,4 +268,12 @@ private static Optional toMotorAlignmentValue(InvertType in ? Optional.of(MotorAlignmentValue.Aligned) : Optional.of(MotorAlignmentValue.Opposed); } + + private static InvertedValue toInvertedValue(InvertType invertType) { + Objects.requireNonNull(invertType, "invertType should not be null"); + return InvertTypes.toInvertValue(invertType) + .orElseThrow( + () -> + new IllegalArgumentException("invertType must be CLOCKWISE or COUNTER_CLOCKWISE")); + } } diff --git a/vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/InvertTypesTest.java b/vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/InvertTypesTest.java new file mode 100644 index 00000000..412aa1ee --- /dev/null +++ b/vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/InvertTypesTest.java @@ -0,0 +1,49 @@ +/* +Copyright 2026 Prospect Robotics SWENext Club + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package com.team2813.lib2813.vendor.ctre; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.ctre.phoenix6.signals.InvertedValue; +import com.team2813.lib2813.control.InvertType; +import java.util.Optional; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.FieldSource; + +/** Tests for {@link InvertTypes}. */ +class InvertTypesTest { + + @ParameterizedTest + @FieldSource("com.team2813.lib2813.control.InvertType#rotationValues") + public void toInvertValue(InvertType invertType) { + Optional value = InvertTypes.toInvertValue(invertType); + + assertWithMessage("No InvertedValue exists for InvertType.%s", invertType) + .that(value) + .isPresent(); + } + + @ParameterizedTest + @EnumSource(InvertedValue.class) + public void toInvertType(InvertedValue invertedValue) { + InvertType invertType = InvertTypes.toInvertType(invertedValue); + + assertThat(invertType).isNotNull(); + assertThat(InvertTypes.toInvertValue(invertType)).hasValue(invertedValue); + } +} diff --git a/lib/src/test/java/com/team2813/lib2813/control/motors/TalonFXEqualsTest.java b/vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/motor/TalonFXEqualsTest.java similarity index 89% rename from lib/src/test/java/com/team2813/lib2813/control/motors/TalonFXEqualsTest.java rename to vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/motor/TalonFXEqualsTest.java index 3a167d5f..821aff57 100644 --- a/lib/src/test/java/com/team2813/lib2813/control/motors/TalonFXEqualsTest.java +++ b/vendor/ctre/src/test/java/com/team2813/lib2813/vendor/ctre/motor/TalonFXEqualsTest.java @@ -1,5 +1,5 @@ /* -Copyright 2023-2025 Prospect Robotics SWENext Club +Copyright 2023-2026 Prospect Robotics SWENext Club Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.team2813.lib2813.control.motors; +package com.team2813.lib2813.vendor.ctre.motor; import static org.junit.Assert.assertEquals; diff --git a/lib/vendordeps/Phoenix6.json b/vendor/ctre/vendordeps/Phoenix6.json similarity index 100% rename from lib/vendordeps/Phoenix6.json rename to vendor/ctre/vendordeps/Phoenix6.json