-
Notifications
You must be signed in to change notification settings - Fork 0
Param intake #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Param intake #61
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
eedc812
Attempted to add the ParametrizedIntakeSubsystem.java from Robot 2025…
atlanticbomber ab19fc7
run the formatter
cuttestkittensrule 5a43195
Fixed File naming error and made ParameterizedIntakeSubsystem public
atlanticbomber f30285e
added ParameterizedIntakeSubsystemTest to lib2813.
atlanticbomber b882d77
Finished migrating ParameterizedIntakeSubsystemTest to lib2813. FakeP…
atlanticbomber File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
lib/src/main/java/com/team2813/lib2813/subsystems/ParameterizedIntakeSubsystem.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| package com.team2813.lib2813.subsystems; | ||
|
|
||
| import com.google.auto.value.AutoBuilder; | ||
| import com.team2813.lib2813.control.ControlMode; | ||
| import com.team2813.lib2813.control.PIDMotor; | ||
| import edu.wpi.first.wpilibj2.command.Command; | ||
| import edu.wpi.first.wpilibj2.command.InstantCommand; | ||
| import edu.wpi.first.wpilibj2.command.SubsystemBase; | ||
|
|
||
| public abstract class ParameterizedIntakeSubsystem extends SubsystemBase implements AutoCloseable { | ||
| private final PIDMotor intakeMotor; | ||
| private final Params params; | ||
|
|
||
| public record Params(ControlMode controlMode, double intakeDemand, double outtakeDemand) { | ||
|
|
||
| public static Params.Builder builder() { | ||
| return new AutoBuilder_ParameterizedIntakeSubsystem_Params_Builder() | ||
| .setControlMode(ControlMode.VOLTAGE); | ||
| } | ||
|
|
||
| @AutoBuilder | ||
| public interface Builder { | ||
| Builder setControlMode(ControlMode controlMode); | ||
|
|
||
| Builder setIntakeDemand(double demand); | ||
|
|
||
| Builder setOuttakeDemand(double demand); | ||
|
|
||
| Params build(); | ||
| } | ||
|
|
||
| public Params { | ||
| if (controlMode == null) { | ||
| throw new IllegalArgumentException("controlMode cannot be null"); | ||
| } | ||
| if (isEssentiallyZero(intakeDemand)) { | ||
| throw new IllegalArgumentException("intakeDemand cannot be zero"); | ||
| } | ||
| if (isEssentiallyZero(outtakeDemand)) { | ||
| throw new IllegalArgumentException("outtakeDemand cannot be zero"); | ||
| } | ||
| if (Math.signum(intakeDemand) == Math.signum(outtakeDemand)) { | ||
| throw new IllegalArgumentException( | ||
| "intakeDemand should be the opposite sign of outtakeDemand"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| protected ParameterizedIntakeSubsystem(PIDMotor intakeMotor, Params params) { | ||
| this.intakeMotor = intakeMotor; | ||
| this.params = params; | ||
| } | ||
|
|
||
| public final Command intakeItemCommand() { | ||
| return new InstantCommand(this::intakeGamePiece, this); | ||
| } | ||
|
|
||
| public final Command outtakeItemCommand() { | ||
| return new InstantCommand(this::outtakeGamePiece, this); | ||
| } | ||
|
|
||
| public final Command stopMotorCommand() { | ||
| return new InstantCommand(this::stopMotor, this); | ||
| } | ||
|
|
||
| /** Makes intake wheels spin in the intake direction. */ | ||
| protected final void intakeGamePiece() { | ||
| // FIXME: Maybe add a check that the wheels are not stalled. | ||
| setMotorDemand(params.intakeDemand); | ||
| } | ||
|
|
||
| /** Makes intake wheels spin in the outtake direction. */ | ||
| protected final void outtakeGamePiece() { | ||
| setMotorDemand(params.outtakeDemand); | ||
| } | ||
|
|
||
| /** | ||
| * Runs the motor with the provided demand value. | ||
| * | ||
| * @param demand Demand of the motor. Meaning depends on the {@code ControlMode}. | ||
| */ | ||
| protected final void setMotorDemand(double demand) { | ||
| intakeMotor.set(params.controlMode, demand); | ||
| } | ||
|
|
||
| /** | ||
| * Returns a command that runs the motor with the provided demand value. | ||
| * | ||
| * @param demand Demand of the motor. Meaning depends on the {@code ControlMode}. | ||
| */ | ||
| protected final Command setMotorDemandCommand(double demand) { | ||
| return new InstantCommand(() -> setMotorDemand(demand), this); | ||
| } | ||
|
|
||
| /** Stops the motor. */ | ||
| public final void stopMotor() { | ||
| setMotorDemand(0.0); | ||
| } | ||
|
|
||
| @Override | ||
| public void close() {} | ||
|
|
||
| private static boolean isEssentiallyZero(double value) { | ||
| return Math.abs(value) < 0.001; | ||
| } | ||
| } |
39 changes: 39 additions & 0 deletions
39
lib/src/main/java/com/team2813/lib2813/util/FakePIDMotor.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package com.team2813.lib2813.util; | ||
|
|
||
| import com.google.common.truth.Truth; | ||
| import com.team2813.lib2813.control.ControlMode; | ||
| import com.team2813.lib2813.control.PIDMotor; | ||
| import edu.wpi.first.units.Units; | ||
| import edu.wpi.first.units.measure.AngularVelocity; | ||
|
|
||
| public abstract class FakePIDMotor implements PIDMotor { | ||
| public double demand = 0.0f; | ||
| private ControlMode controlMode; | ||
|
|
||
| public double getVoltage() { | ||
| Truth.assertThat(controlMode).isEqualTo(ControlMode.VOLTAGE); | ||
| return demand; | ||
| } | ||
|
|
||
| @Override | ||
| public void set(ControlMode mode, double demand) { | ||
| Truth.assertThat(mode).isNotNull(); | ||
| controlMode = mode; | ||
| this.demand = demand; | ||
| } | ||
|
|
||
| @Override | ||
| public void set(ControlMode mode, double demand, double feedForward) { | ||
| set(mode, demand); | ||
| } | ||
|
|
||
| @Override | ||
| public AngularVelocity getVelocityMeasure() { | ||
| return Units.RadiansPerSecond.of(demand * 20); | ||
| } | ||
|
|
||
| @Override | ||
| public double getVelocity() { | ||
| throw new AssertionError("Called deprecated method"); | ||
| } | ||
| } |
111 changes: 111 additions & 0 deletions
111
lib/src/test/java/com/team2813/lib2813/subsystems/ParameterizedIntakeSubsystemTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| package com.team2813.lib2813.subsystems; | ||
|
|
||
| import static com.google.common.truth.Truth.assertThat; | ||
| import static org.mockito.Mockito.mock; | ||
| import static org.mockito.Mockito.verifyNoInteractions; | ||
|
|
||
| import com.team2813.lib2813.control.ControlMode; | ||
| import com.team2813.lib2813.control.PIDMotor; | ||
| import com.team2813.lib2813.testing.junit.jupiter.CommandTester; | ||
| import com.team2813.lib2813.testing.junit.jupiter.WPILibExtension; | ||
| import com.team2813.lib2813.util.FakePIDMotor; | ||
| import edu.wpi.first.wpilibj2.command.Command; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.junit.jupiter.api.extension.ExtendWith; | ||
| import org.junit.jupiter.params.ParameterizedClass; | ||
| import org.junit.jupiter.params.provider.EnumSource; | ||
| import org.mockito.Answers; | ||
|
|
||
| @ParameterizedClass | ||
| @EnumSource(ControlMode.class) | ||
| @ExtendWith(WPILibExtension.class) | ||
| public final class ParameterizedIntakeSubsystemTest { | ||
|
|
||
| private static class ConcreteParameterizedIntakeSubsystem extends ParameterizedIntakeSubsystem { | ||
| protected ConcreteParameterizedIntakeSubsystem(PIDMotor intakeMotor, Params params) { | ||
| super(intakeMotor, params); | ||
| } | ||
| } | ||
|
|
||
| final FakePIDMotor fakeMotor = mock(FakePIDMotor.class, Answers.CALLS_REAL_METHODS); | ||
| private final ParameterizedIntakeSubsystem.Params params; | ||
|
|
||
| public ParameterizedIntakeSubsystemTest(ControlMode controlMode) { | ||
| params = | ||
| ParameterizedIntakeSubsystem.Params.builder() | ||
| .setControlMode(controlMode) | ||
| .setIntakeDemand(42) | ||
| .setOuttakeDemand(-3.1415) | ||
| .build(); | ||
| } | ||
|
|
||
| @Test | ||
| public void initialState() { | ||
| try (var ignored = new ConcreteParameterizedIntakeSubsystem(fakeMotor, params)) { | ||
| assertMotorIsStopped(); | ||
| verifyNoInteractions(fakeMotor); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void intakeItem(CommandTester commandTester) { | ||
| try (var intake = new ConcreteParameterizedIntakeSubsystem(fakeMotor, params)) { | ||
| Command command = intake.intakeItemCommand(); | ||
| assertMotorIsStopped(); | ||
|
|
||
| commandTester.runUntilComplete(command); | ||
|
|
||
| assertThat(fakeMotor.demand).isWithin(0.01).of(params.intakeDemand()); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void stopAfterIntakingItem(CommandTester commandTester) { | ||
| try (var intake = new ConcreteParameterizedIntakeSubsystem(fakeMotor, params)) { | ||
| Command command = intake.intakeItemCommand(); | ||
| commandTester.runUntilComplete(command); | ||
| command = intake.stopMotorCommand(); | ||
| assertMotorIsRunning(); | ||
|
|
||
| commandTester.runUntilComplete(command); | ||
|
|
||
| assertMotorIsStopped(); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void outtakeItem(CommandTester commandTester) { | ||
| try (var intake = new ConcreteParameterizedIntakeSubsystem(fakeMotor, params)) { | ||
| intake.intakeGamePiece(); | ||
| Command command = intake.outtakeItemCommand(); | ||
| assertMotorIsRunning(); | ||
|
|
||
| commandTester.runUntilComplete(command); | ||
|
|
||
| assertThat(fakeMotor.demand).isWithin(0.01).of(params.outtakeDemand()); | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| public void stopAfterOuttakingItem(CommandTester commandTester) { | ||
| try (var intake = new ConcreteParameterizedIntakeSubsystem(fakeMotor, params)) { | ||
| intake.intakeGamePiece(); | ||
| Command command = intake.outtakeItemCommand(); | ||
| commandTester.runUntilComplete(command); | ||
| command = intake.stopMotorCommand(); | ||
| assertMotorIsRunning(); | ||
|
|
||
| commandTester.runUntilComplete(command); | ||
|
|
||
| assertMotorIsStopped(); | ||
| } | ||
| } | ||
|
|
||
| private void assertMotorIsStopped() { | ||
| assertThat(fakeMotor.demand).isWithin(0.01).of(0.0); | ||
| } | ||
|
|
||
| private void assertMotorIsRunning() { | ||
| assertThat(fakeMotor.demand).isNotWithin(0.01).of(0.0); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having
:lib2813:libdepend on Truth would add a lot of classes to the code deployed to the robot. We should avoid that if possible.I think it would be best to move
FakePIDMotor to:lib2813:testing`There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@atlanticbomber ^^^