Skip to content
This repository has been archived by the owner on Apr 20, 2024. It is now read-only.

Commit

Permalink
Intake subsystem (#6)
Browse files Browse the repository at this point in the history
* create new intake subsystem

* make intake states better

---------

Co-authored-by: Aidan <>
Co-authored-by: Jordan <117786700+jordanjcoderman@users.noreply.github.com>
  • Loading branch information
rhetorr and jordanjcoderman authored Feb 11, 2024
1 parent 61e34bc commit 44c775c
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 282 deletions.
3 changes: 1 addition & 2 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ public class Robot extends LoggedRobot {
RobotConfig.get().climber().followerMotorID(), RobotConfig.get().canivoreName()));
private final IntakeSubsystem intake =
new IntakeSubsystem(
new TalonFX(RobotConfig.get().intake().topMotorID(), RobotConfig.get().canivoreName()),
new TalonFX(RobotConfig.get().intake().bottomMotorID(), RobotConfig.get().canivoreName()),
new TalonFX(RobotConfig.get().intake().motorID(), RobotConfig.get().canivoreName()),
new DigitalInput(RobotConfig.get().intake().sensorID()));
private final SwerveSubsystem swerve = new SwerveSubsystem(driverController);
private final ImuSubsystem imu = new ImuSubsystem(swerve);
Expand Down
9 changes: 1 addition & 8 deletions src/main/java/frc/robot/config/CompConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,21 +162,14 @@ class CompConfig {
0.0),
new IntakeConfig(
16,
22,
0,
// Top Motor
new TalonFXConfiguration()
.withFeedback(new FeedbackConfigs().withSensorToMechanismRatio(1))
.withCurrentLimits(new CurrentLimitsConfigs().withSupplyCurrentLimit(20))
.withMotorOutput(
new MotorOutputConfigs()
.withInverted(InvertedValue.CounterClockwise_Positive)),
// Bottom Motor
new TalonFXConfiguration()
.withFeedback(new FeedbackConfigs().withSensorToMechanismRatio(1))
.withCurrentLimits(new CurrentLimitsConfigs().withSupplyCurrentLimit(20))
.withMotorOutput(
new MotorOutputConfigs().withInverted(InvertedValue.Clockwise_Positive))),
.withInverted(InvertedValue.CounterClockwise_Positive))),
new QueuerConfig(
0,
0,
Expand Down
10 changes: 1 addition & 9 deletions src/main/java/frc/robot/config/PracticeConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,21 +149,13 @@ class PracticeConfig {
0.0),
new IntakeConfig(
16,
22,
0,
// Top Motor
new TalonFXConfiguration()
.withFeedback(new FeedbackConfigs().withSensorToMechanismRatio(1))
.withCurrentLimits(new CurrentLimitsConfigs().withSupplyCurrentLimit(20))
.withMotorOutput(
new MotorOutputConfigs().withInverted(InvertedValue.Clockwise_Positive)),
// Bottom Motor
new TalonFXConfiguration()
.withFeedback(new FeedbackConfigs().withSensorToMechanismRatio(1))
.withCurrentLimits(new CurrentLimitsConfigs().withSupplyCurrentLimit(20))
.withMotorOutput(
new MotorOutputConfigs()
.withInverted(InvertedValue.CounterClockwise_Positive))),
new MotorOutputConfigs().withInverted(InvertedValue.Clockwise_Positive))),
new QueuerConfig(
0,
0,
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/frc/robot/config/RobotConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,9 @@ public record ClimberConfig(
int mainMotorID, int followerMotorID, TalonFXConfiguration motorConfig) {}

public record IntakeConfig(
int topMotorID,
int bottomMotorID,
int motorID,
int sensorID,
TalonFXConfiguration topMotorConfig,
TalonFXConfiguration bottomMotorConfig) {}
TalonFXConfiguration motorConfig) {}

public record QueuerConfig(int motorID, int sensorID, TalonFXConfiguration motorConfig) {}

Expand Down
19 changes: 5 additions & 14 deletions src/main/java/frc/robot/intake/IntakeState.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,9 @@
package frc.robot.intake;

public enum IntakeState {
IDLE_NO_GP,
IDLE_WITH_GP,

// Intaking, waitinf or sensor to trigger for the first time
INTAKING_GP_WAITING_FOR_SENSOR_ON,
// Intaking, wait for the note to pass all the way through, and stop triggering the sensor
INTAKING_GP_WAITING_FOR_SENSOR_OFF,
// Intaking in reverse, waiting for note to hit sensor again, then we transition to IDLE_WITH_GP
INTAKING_GP_FINAL_WAITING_FOR_SENSOR_ON,

OUTTAKING,
SHOOTING,
TRAP_OUTTAKE,
CLIMBING;
IDLE,
INTAKING,
PASS_TO_QUEUER,
PASS_TO_CONVEYOR,
OUTTAKING;
}
237 changes: 48 additions & 189 deletions src/main/java/frc/robot/intake/IntakeSubsystem.java
Original file line number Diff line number Diff line change
@@ -1,235 +1,94 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package frc.robot.intake;

import com.ctre.phoenix6.controls.VoltageOut;
import com.ctre.phoenix6.hardware.TalonFX;

import edu.wpi.first.wpilibj.DigitalInput;
import frc.robot.config.RobotConfig;
import frc.robot.util.scheduling.LifecycleSubsystem;
import frc.robot.util.scheduling.SubsystemPriority;
import org.littletonrobotics.junction.Logger;

public class IntakeSubsystem extends LifecycleSubsystem {
private final TalonFX topMotor;
private final TalonFX bottomMotor;
private final TalonFX motor;
private final DigitalInput sensor;
private IntakeState state = IntakeState.IDLE_NO_GP;
private final VoltageOut voltageRequest = new VoltageOut(0).withEnableFOC(false);

private boolean idleFlag = false;
private boolean idleWithGPFlag = false;
private boolean idleNoGPFlag = false;
private boolean intakingFlag = false;
private boolean outtakingFlag = false;
private boolean shootingFlag = false;
private boolean trapOuttakeFlag = false;
private boolean climbingFlag = false;
private VoltageOut voltageRequest = new VoltageOut(0.0);
private IntakeState goalState = IntakeState.IDLE;
private double voltageUsed = 0.0;
private boolean hasNote = false;

public IntakeSubsystem(TalonFX topMotor, TalonFX bottomMotor, DigitalInput sensor) {
public IntakeSubsystem(TalonFX motor, DigitalInput sensor) {
super(SubsystemPriority.INTAKE);

this.topMotor = topMotor;
motor.getConfigurator().apply(RobotConfig.get().intake().motorConfig());

this.motor = motor;
this.sensor = sensor;
this.bottomMotor = bottomMotor;

topMotor.getConfigurator().apply(RobotConfig.get().intake().topMotorConfig());
bottomMotor.getConfigurator().apply(RobotConfig.get().intake().bottomMotorConfig());
}

@Override
public void enabledPeriodic() {
Logger.recordOutput("Intake/State", state);

Logger.recordOutput("Intake/IdleFlag", idleFlag);
Logger.recordOutput("Intake/IdleWithGPFlag", idleWithGPFlag);
Logger.recordOutput("Intake/IdleNoGPFlag", idleNoGPFlag);
Logger.recordOutput("Intake/IntakingFlag", intakingFlag);
Logger.recordOutput("Intake/OuttakingFlag", outtakingFlag);
Logger.recordOutput("Intake/ShootingFlag", shootingFlag);
Logger.recordOutput("Intake/TrapOuttakeFlag", trapOuttakeFlag);
Logger.recordOutput("Intake/ClimbingFlag", climbingFlag);

Logger.recordOutput("Intake/SensorHasNote", sensorHasNote());

Logger.recordOutput("Intake/TopMotor/Current", topMotor.getStatorCurrent().getValueAsDouble());
Logger.recordOutput("Intake/TopMotor/Velocity", topMotor.getVelocity().getValueAsDouble());
Logger.recordOutput(
"Intake/TopMotor/OutputVoltage", topMotor.getMotorVoltage().getValueAsDouble());
Logger.recordOutput("Intake/TopMotor/Temperature", topMotor.getDeviceTemp().getValue());

Logger.recordOutput(
"Intake/BottomMotor/Current", bottomMotor.getStatorCurrent().getValueAsDouble());
Logger.recordOutput(
"Intake/BottomMotor/Velocity", bottomMotor.getVelocity().getValueAsDouble());
Logger.recordOutput(
"Intake/BottomMotor/OutputVoltage", bottomMotor.getMotorVoltage().getValueAsDouble());
Logger.recordOutput("Intake/BottomMotor/Temperature", bottomMotor.getDeviceTemp().getValue());

// State transitions from requests
if (idleFlag) {
switch (state) {
case IDLE_NO_GP:
case INTAKING_GP_WAITING_FOR_SENSOR_ON:
case OUTTAKING:
case SHOOTING:
case TRAP_OUTTAKE:
state = IntakeState.IDLE_NO_GP;
break;

default:
state = IntakeState.IDLE_WITH_GP;
break;
}
}
if (intakingFlag) {
// Don't interrupt the intake sequence if we are already in it
if (state != IntakeState.INTAKING_GP_WAITING_FOR_SENSOR_OFF
&& state != IntakeState.INTAKING_GP_FINAL_WAITING_FOR_SENSOR_ON) {

state = IntakeState.INTAKING_GP_WAITING_FOR_SENSOR_ON;
}
}
if (outtakingFlag) {
state = IntakeState.OUTTAKING;
}
if (trapOuttakeFlag) {
state = IntakeState.TRAP_OUTTAKE;
}
if (climbingFlag) {
state = IntakeState.CLIMBING;
}
if (shootingFlag) {
state = IntakeState.SHOOTING;
}
if (idleWithGPFlag) {
state = IntakeState.IDLE_WITH_GP;
}
if (idleNoGPFlag) {
state = IntakeState.IDLE_NO_GP;
}

// Automatic state transitions
switch (state) {
case IDLE_WITH_GP:
case CLIMBING:
case IDLE_NO_GP:
// Do nothing
break;
case INTAKING_GP_WAITING_FOR_SENSOR_ON:
if (sensorHasNote()) {
state = IntakeState.INTAKING_GP_WAITING_FOR_SENSOR_OFF;
}
break;
case INTAKING_GP_WAITING_FOR_SENSOR_OFF:
if (!sensorHasNote()) {
state = IntakeState.INTAKING_GP_FINAL_WAITING_FOR_SENSOR_ON;
}
break;
case INTAKING_GP_FINAL_WAITING_FOR_SENSOR_ON:
if (sensorHasNote()) {
state = IntakeState.IDLE_WITH_GP;
}
switch (goalState) {
case IDLE:
voltageUsed = 0.0;
break;
case OUTTAKING:
case SHOOTING:
case TRAP_OUTTAKE:
if (!sensorHasNote()) {
state = IntakeState.IDLE_NO_GP;
}
break;
}

// State actions

// negative voltage intake
// positive voltage outtake
switch (state) {
case IDLE_WITH_GP:
case IDLE_NO_GP:
topMotor.disable();
bottomMotor.disable();
voltageUsed = -4.0;
break;
case INTAKING_GP_WAITING_FOR_SENSOR_ON:
topMotor.setControl(voltageRequest.withOutput(-3.5));
bottomMotor.setControl(voltageRequest.withOutput(-3.5));
case PASS_TO_CONVEYOR:
voltageUsed = 2.0;
break;
case INTAKING_GP_WAITING_FOR_SENSOR_OFF:
topMotor.setControl(voltageRequest.withOutput(-1.0));
bottomMotor.setControl(voltageRequest.withOutput(-1.0));
case PASS_TO_QUEUER:
voltageUsed = 2.0;
break;
case INTAKING_GP_FINAL_WAITING_FOR_SENSOR_ON:
topMotor.setControl(voltageRequest.withOutput(1.0));
bottomMotor.setControl(voltageRequest.withOutput(1.0));
case INTAKING:
voltageUsed = 4.0;
break;
case OUTTAKING:
topMotor.setControl(voltageRequest.withOutput(6.0));
bottomMotor.setControl(voltageRequest.withOutput(6.0));
break;
case SHOOTING:
topMotor.setControl(voltageRequest.withOutput(-10.0));
bottomMotor.setControl(voltageRequest.withOutput(-10.0));
break;
case TRAP_OUTTAKE:
topMotor.setControl(voltageRequest.withOutput(6.0));
bottomMotor.setControl(voltageRequest.withOutput(-6.0));
break;
case CLIMBING:
topMotor.disable();
bottomMotor.setControl(voltageRequest.withOutput(-10.0));
default:
break;
}

// Reset all flags
idleFlag = false;
idleNoGPFlag = false;
idleWithGPFlag = false;
intakingFlag = false;
outtakingFlag = false;
shootingFlag = false;
trapOuttakeFlag = false;
climbingFlag = false;
}

public void idleRequest() {
idleFlag = true;
}

public void intakingRequest() {
intakingFlag = true;
}

public void outtakingRequest() {
outtakingFlag = true;
if (goalState == IntakeState.IDLE) {
motor.disable();
} else {
voltageRequest.withOutput(voltageUsed);
}
setHasNote(sensorHasNote());
}

public void shootingRequest() {
shootingFlag = true;
public void setState(IntakeState state) {
goalState = state;
}

public void trapOuttakeRequest() {
trapOuttakeFlag = true;
}
public boolean atGoal(IntakeState state) {
if (goalState != state) {
return false;
}

public void climbingRequest() {
climbingFlag = true;
if (goalState == IntakeState.IDLE) {
return true;
}
if (hasNote) {
return true;
}
if (Math.abs(motor.getMotorVoltage().getValue()) > 0.0 && !hasNote) {
return true;
}
return false;
}

public void idleWithGPRequest() {
idleWithGPFlag = true;
public boolean getHasNote() {
return hasNote;
}

public void idleNoGPRequest() {
idleNoGPFlag = true;
public void setHasNote(boolean bool) {
hasNote = bool;
}

private boolean sensorHasNote() {
return sensor.get();
}

public IntakeState getState() {
return state;
return goalState;
}
}
Loading

0 comments on commit 44c775c

Please sign in to comment.