Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions buildSrc/src/main/groovy/java-common-conventions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -107,7 +107,7 @@ spotless {

formatAnnotations() // fix formatting of type annotations

licenseHeaderFile("../java-copyright-header.txt")
licenseHeaderFile("$rootDir/java-copyright-header.txt")
}
}

Expand Down
10 changes: 8 additions & 2 deletions buildSrc/src/main/groovy/publishing-conventions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
42 changes: 7 additions & 35 deletions lib/src/main/java/com/team2813/lib2813/control/InvertType.java
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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;

Expand All @@ -34,49 +33,27 @@ public enum InvertType {
public static final Set<InvertType> rotationValues =
Collections.unmodifiableSet(EnumSet.of(CLOCKWISE, COUNTER_CLOCKWISE));

private final Optional<InvertedValue> phoenixInvert;
private final Optional<Boolean> 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<InvertType> 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}
*/
public static Optional<InvertType> fromSparkMaxInvert(boolean v) {
return Optional.of(Maps.sparkMaxMap.get(v));
}

public Optional<InvertedValue> phoenixInvert() {
return phoenixInvert;
}

private InvertedValue forcePhoenixInvert() {
return phoenixInvert.orElseThrow();
}

public Optional<Boolean> sparkMaxInvert() {
return sparkMaxInvert;
}
Expand All @@ -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<InvertedValue, InvertType> phoenixMap =
Stream.of(InvertType.values())
.filter((j) -> j.phoenixInvert.isPresent())
.collect(toUnmodifiableMap(InvertType::forcePhoenixInvert, (j) -> j, (a, b) -> null));
private static final Map<Boolean, InvertType> sparkMaxMap =
Stream.of(InvertType.values())
.filter((j) -> j.sparkMaxInvert.isPresent())
Expand Down
13 changes: 0 additions & 13 deletions lib/src/main/java/com/team2813/lib2813/util/ConfigUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -39,16 +38,4 @@ public static void revConfig(Supplier<REVLibError> configMethod) {
DriverStation.reportError(String.format("%s: Config Failed", errorCode.toString()), false);
}
}

public static void phoenix6Config(Supplier<StatusCode> 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);
}
}
}
21 changes: 2 additions & 19 deletions lib/src/test/java/com/team2813/lib2813/control/InvertTypeTest.java
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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());
}
}

Expand Down
6 changes: 2 additions & 4 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@
*/

rootProject.name = 'lib2813'
include('lib')
include('limelight')
include('vision')
include('testing')
include 'lib', 'limelight', 'vision', 'testing'
include 'vendor:ctre'
45 changes: 45 additions & 0 deletions vendor/ctre/build.gradle
Original file line number Diff line number Diff line change
@@ -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'
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<InvertedValue> 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");
}
}
Original file line number Diff line number Diff line change
@@ -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<StatusCode> 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");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down
Loading