Skip to content

Commit adeabaf

Browse files
committed
Add vendor-rev project
1 parent d401014 commit adeabaf

9 files changed

Lines changed: 173 additions & 106 deletions

File tree

lib/src/main/java/com/team2813/lib2813/control/InvertType.java

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515
*/
1616
package com.team2813.lib2813.control;
1717

18-
import static java.util.stream.Collectors.toUnmodifiableMap;
19-
20-
import java.util.*;
21-
import java.util.stream.Stream;
18+
import java.util.Collections;
19+
import java.util.EnumSet;
20+
import java.util.Set;
2221

2322
public enum InvertType {
24-
CLOCKWISE(true),
25-
COUNTER_CLOCKWISE(false),
23+
CLOCKWISE,
24+
COUNTER_CLOCKWISE,
2625
FOLLOW_MASTER,
2726
OPPOSE_MASTER;
2827

@@ -32,44 +31,4 @@ public enum InvertType {
3231
*/
3332
public static final Set<InvertType> rotationValues =
3433
Collections.unmodifiableSet(EnumSet.of(CLOCKWISE, COUNTER_CLOCKWISE));
35-
36-
private final Optional<Boolean> sparkMaxInvert;
37-
38-
InvertType() {
39-
sparkMaxInvert = Optional.empty();
40-
}
41-
42-
InvertType(boolean sparkMaxInvert) {
43-
this.sparkMaxInvert = Optional.of(sparkMaxInvert);
44-
}
45-
46-
/**
47-
* Gets an {@link InvertType} from a spark max invert
48-
*
49-
* @param v the value to search for
50-
* @return {@link Optional#empty()} if no {@link InvertType} is found, otherwise, an optional
51-
* describing the {@link InvertType}
52-
*/
53-
public static Optional<InvertType> fromSparkMaxInvert(boolean v) {
54-
return Optional.of(Maps.sparkMaxMap.get(v));
55-
}
56-
57-
public Optional<Boolean> sparkMaxInvert() {
58-
return sparkMaxInvert;
59-
}
60-
61-
private boolean forceSparkMaxInvert() {
62-
return sparkMaxInvert.orElseThrow();
63-
}
64-
65-
/**
66-
* Contains the maps for {@link InvertType#fromSparkMaxInvert(boolean)}. In a static class so that
67-
* they will only be initialized if they are needed.
68-
*/
69-
private static final class Maps {
70-
private static final Map<Boolean, InvertType> sparkMaxMap =
71-
Stream.of(InvertType.values())
72-
.filter((j) -> j.sparkMaxInvert.isPresent())
73-
.collect(toUnmodifiableMap(InvertType::forceSparkMaxInvert, (j) -> j, (a, b) -> null));
74-
}
7534
}

lib/src/test/java/com/team2813/lib2813/control/InvertTypeTest.java

Lines changed: 0 additions & 41 deletions
This file was deleted.

settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99

1010
rootProject.name = 'lib2813'
1111
include 'lib', 'limelight', 'vision', 'testing'
12-
include 'vendor:ctre'
12+
include 'vendor:ctre', 'vendor:rev'

vendor/rev/build.gradle

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
plugins {
2+
id 'java-common-conventions'
3+
id 'publishing-conventions'
4+
id 'edu.wpi.first.GradleRIO' version '2026.1.1'
5+
}
6+
7+
dependencies {
8+
implementation wpi.java.deps.wpilib()
9+
implementation wpi.java.vendor.java()
10+
implementation project(':lib')
11+
12+
nativeDebug wpi.java.deps.wpilibJniDebug(wpi.platforms.desktop)
13+
nativeDebug wpi.java.vendor.jniDebug(wpi.platforms.desktop)
14+
simulationDebug wpi.sim.enableDebug()
15+
16+
nativeRelease wpi.java.deps.wpilibJniRelease(wpi.platforms.desktop)
17+
nativeRelease wpi.java.vendor.jniRelease(wpi.platforms.desktop)
18+
simulationRelease wpi.sim.enableRelease()
19+
20+
testImplementation(platform('org.junit:junit-bom:5.13.1'))
21+
testImplementation('org.junit.jupiter:junit-jupiter')
22+
testImplementation('com.google.truth:truth:1.4.4')
23+
testRuntimeOnly('org.junit.platform:junit-platform-launcher')
24+
}
25+
26+
// the magic line that makes tests work :)
27+
wpi.java.configureTestTasks(test)
28+
29+
tasks.named('test') {
30+
useJUnitPlatform()
31+
}
32+
33+
mavenPublishing {
34+
pom {
35+
name = '2813 REV Robotics Vendor Library'
36+
description = 'REV Robotics extensions to team2813:lib'
37+
developers {
38+
developer {
39+
id = 'cuttestkittensrule'
40+
name = 'Kyle'
41+
email = 'mangoiscute95@gmail.com'
42+
}
43+
}
44+
}
45+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright 2026 Prospect Robotics SWENext Club
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package com.team2813.lib2813.vendor.rev;
17+
18+
import com.team2813.lib2813.control.InvertType;
19+
import java.util.Objects;
20+
import java.util.Optional;
21+
22+
/** Utility methods for working with {@link InvertType} for REV Robotics motors. */
23+
public class InvertTypes {
24+
25+
/**
26+
* Gets the SPARK MAX invert value for the given {@link InvertType}
27+
*
28+
* @return The invert, or {@link Optional#empty()} if the provided {@code invertType} is not a
29+
* rotational value.
30+
*/
31+
public static Optional<Boolean> toSparkMaxInvert(InvertType invertType) {
32+
return switch (Objects.requireNonNull(invertType, "invertType should not be null")) {
33+
case CLOCKWISE -> Optional.of(Boolean.TRUE);
34+
case COUNTER_CLOCKWISE -> Optional.of(Boolean.FALSE);
35+
default -> Optional.empty();
36+
};
37+
}
38+
39+
/** Gets the {@link InvertType} for the given SPARK MAX invert value. */
40+
public static InvertType toInvertType(boolean sparkMaxInvert) {
41+
return sparkMaxInvert ? InvertType.CLOCKWISE : InvertType.COUNTER_CLOCKWISE;
42+
}
43+
44+
private InvertTypes() {
45+
throw new AssertionError("Not instantiable");
46+
}
47+
}

lib/src/main/java/com/team2813/lib2813/util/ConfigUtils.java renamed to vendor/rev/src/main/java/com/team2813/lib2813/vendor/rev/RevUtils.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,15 @@
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
package com.team2813.lib2813.util;
16+
package com.team2813.lib2813.vendor.rev;
1717

1818
import com.revrobotics.REVLibError;
1919
import edu.wpi.first.wpilibj.DriverStation;
2020
import java.util.function.Supplier;
2121

22-
public class ConfigUtils {
22+
public class RevUtils {
2323
private static final int ATTEMPTS = 10;
2424

25-
// make class non-instantiable
26-
private ConfigUtils() {
27-
throw new AssertionError("cannot create ConfigUtils instance");
28-
}
29-
3025
public static void revConfig(Supplier<REVLibError> configMethod) {
3126
REVLibError errorCode = configMethod.get();
3227
for (int i = 1; i <= ATTEMPTS && errorCode != REVLibError.kOk; i++) {
@@ -38,4 +33,8 @@ public static void revConfig(Supplier<REVLibError> configMethod) {
3833
DriverStation.reportError(String.format("%s: Config Failed", errorCode.toString()), false);
3934
}
4035
}
36+
37+
private RevUtils() {
38+
throw new AssertionError("Not instantiable");
39+
}
4140
}

lib/src/main/java/com/team2813/lib2813/control/motors/SparkMaxWrapper.java renamed to vendor/rev/src/main/java/com/team2813/lib2813/vendor/rev/motor/SparkMaxWrapper.java

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
package com.team2813.lib2813.control.motors;
16+
package com.team2813.lib2813.vendor.rev.motor;
1717

1818
import com.revrobotics.RelativeEncoder;
1919
import com.revrobotics.spark.ClosedLoopSlot;
@@ -27,13 +27,15 @@
2727
import com.team2813.lib2813.control.ControlMode;
2828
import com.team2813.lib2813.control.InvertType;
2929
import com.team2813.lib2813.control.PIDMotor;
30-
import com.team2813.lib2813.util.ConfigUtils;
30+
import com.team2813.lib2813.vendor.rev.InvertTypes;
31+
import com.team2813.lib2813.vendor.rev.RevUtils;
3132
import edu.wpi.first.units.Units;
3233
import edu.wpi.first.units.measure.Angle;
3334
import edu.wpi.first.units.measure.AngularVelocity;
3435
import edu.wpi.first.units.measure.Current;
3536
import java.util.ArrayList;
3637
import java.util.List;
38+
import java.util.Objects;
3739

3840
public class SparkMaxWrapper implements PIDMotor {
3941
private final List<SparkMax> followers = new ArrayList<>();
@@ -51,15 +53,15 @@ public class SparkMaxWrapper implements PIDMotor {
5153
* @param type The motor type connected to the controller. Brushless motor wires must be connected
5254
* to their matching colors and the hall sensor must be plugged in. Brushed motors must be
5355
* connected to the Red and Black terminals only.
54-
* @param inverted Whether the motor is inverted
56+
* @param invertType Whether the motor is inverted
5557
*/
56-
public SparkMaxWrapper(int deviceId, SparkLowLevel.MotorType type, InvertType inverted) {
58+
public SparkMaxWrapper(int deviceId, SparkLowLevel.MotorType type, InvertType invertType) {
5759
motor = new SparkMax(deviceId, type);
58-
this.inverted = inverted.sparkMaxInvert().orElseThrow();
60+
this.inverted = toSparkMaxInvert(invertType);
5961
config = new SparkMaxConfig().apply(new AlternateEncoderConfig().inverted(this.inverted));
6062
persistMode = SparkBase.PersistMode.kNoPersistParameters;
6163
resetMode = SparkBase.ResetMode.kResetSafeParameters;
62-
ConfigUtils.revConfig(() -> motor.configure(config, resetMode, persistMode));
64+
RevUtils.revConfig(() -> motor.configure(config, resetMode, persistMode));
6365
encoder = motor.getEncoder();
6466
}
6567

@@ -116,7 +118,7 @@ public void configPIDF(int slot, double p, double i, double d, double f) {
116118
ClosedLoopConfig closedLoopConfig = new ClosedLoopConfig().pid(p, i, d, cSlot);
117119
closedLoopConfig.feedForward.kV(f, cSlot);
118120
config.apply(closedLoopConfig);
119-
ConfigUtils.revConfig(() -> motor.configure(config, resetMode, persistMode));
121+
RevUtils.revConfig(() -> motor.configure(config, resetMode, persistMode));
120122
}
121123

122124
@Override
@@ -134,18 +136,26 @@ public void configPID(double p, double i, double d) {
134136
configPIDF(0, p, i, d, 0);
135137
}
136138

137-
public void addFollower(int deviceId, SparkLowLevel.MotorType type, InvertType inverted) {
139+
public void addFollower(int deviceId, SparkLowLevel.MotorType type, InvertType invertType) {
138140
SparkMax follower = new SparkMax(deviceId, type);
139141
boolean isInverted =
140-
switch (inverted) {
141-
case CLOCKWISE, COUNTER_CLOCKWISE -> inverted.sparkMaxInvert().orElseThrow();
142+
switch (invertType) {
143+
case CLOCKWISE, COUNTER_CLOCKWISE -> toSparkMaxInvert(invertType);
142144
case FOLLOW_MASTER -> this.inverted;
143145
case OPPOSE_MASTER -> !this.inverted;
144146
};
145-
ConfigUtils.revConfig(
147+
RevUtils.revConfig(
146148
() ->
147149
follower.configure(
148150
new SparkMaxConfig().follow(motor).inverted(isInverted), resetMode, persistMode));
149151
followers.add(follower); // add to follower list so CANSparkMax follower object is preserved
150152
}
153+
154+
private static boolean toSparkMaxInvert(InvertType invertType) {
155+
Objects.requireNonNull(invertType, "invertType should not be null");
156+
return InvertTypes.toSparkMaxInvert(invertType)
157+
.orElseThrow(
158+
() ->
159+
new IllegalArgumentException("invertType must be CLOCKWISE or COUNTER_CLOCKWISE"));
160+
}
151161
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright 2026 Prospect Robotics SWENext Club
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package com.team2813.lib2813.vendor.rev;
17+
18+
import static com.google.common.truth.Truth.assertThat;
19+
import static com.google.common.truth.Truth.assertWithMessage;
20+
21+
import com.team2813.lib2813.control.InvertType;
22+
import java.util.Optional;
23+
import org.junit.jupiter.params.ParameterizedTest;
24+
import org.junit.jupiter.params.provider.FieldSource;
25+
import org.junit.jupiter.params.provider.ValueSource;
26+
27+
/** Tests for {@link InvertTypes}. */
28+
class InvertTypesTest {
29+
30+
@ParameterizedTest
31+
@FieldSource("com.team2813.lib2813.control.InvertType#rotationValues")
32+
public void toSparkMaxInvert(InvertType invertType) {
33+
Optional<Boolean> value = InvertTypes.toSparkMaxInvert(invertType);
34+
35+
assertWithMessage("No InvertedValue exists for InvertType.%s", invertType)
36+
.that(value)
37+
.isPresent();
38+
}
39+
40+
@ParameterizedTest
41+
@ValueSource(booleans = {true, false})
42+
public void toInvertType(boolean sparkMaxInvert) {
43+
InvertType invertType = InvertTypes.toInvertType(sparkMaxInvert);
44+
45+
assertThat(invertType).isNotNull();
46+
assertThat(InvertTypes.toSparkMaxInvert(invertType)).hasValue(sparkMaxInvert);
47+
}
48+
}

0 commit comments

Comments
 (0)