Skip to content

Commit

Permalink
Shooter velocity control (#90)
Browse files Browse the repository at this point in the history
* added a bang bang controller to the shooter wheels, ShooterPIDSubsystem UNUSED

* add driving practice fixes

---------

Co-authored-by: Luhan Wang <[email protected]>
Co-authored-by: Connor Murphy <[email protected]>
  • Loading branch information
3 people authored Feb 22, 2024
1 parent 62750fd commit 076789c
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 23 deletions.
6 changes: 4 additions & 2 deletions src/main/java/org/jmhsrobotics/frc2024/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static class PWM {
}

public static class Arm {
public static double pickupSetpoint = 3;
public static double pickupSetpoint = 5;
public static double shootingSetpoint = 10;
public static double ampSetpoint = 95;
}
Expand Down Expand Up @@ -77,7 +77,9 @@ public static class SwerveConstants {
// Driving Parameters - Note that these are not the maximum capable speeds of
// the robot, rather the allowed maximum speeds
// public static final double kMaxSpeedMetersPerSecond = 4.2;
public static final double kMaxSpeedMetersPerSecond = 2; // testing speed - roughly 6ft/s
public static final double kMaxSpeedFeetPerSecond = 14;
public static final double kMaxSpeedMetersPerSecond = 0.3048 * kMaxSpeedFeetPerSecond; // testing speed -
// roughly 6ft/s
public static final double kMaxAngularSpeed = Math.PI; // radians per second

public static final double kDirectionSlewRate = 1.4; // radians per second
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/jmhsrobotics/frc2024/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ private boolean getAllianceFlipState() {
private void configureBindings() {
this.control.presetMid().onTrue(new ArmSetShootCommand(this.armSubsystem));
this.control.presetLow().onTrue(new ArmSetPickupCommand(this.armSubsystem));
this.control.intakeInput().whileTrue(new IntakeCommand(0.5, this.intakeSubsystem));
this.control.extakeInput().whileTrue(new IntakeCommand(-0.5, this.intakeSubsystem));
this.control.intakeInput().whileTrue(new IntakeCommand(0.5, this.intakeSubsystem, this.shooterSubsystem));
this.control.extakeInput().whileTrue(new IntakeCommand(-0.5, this.intakeSubsystem, this.shooterSubsystem));
this.control.shooterInput().whileTrue(new ShootOpenLoopCommand(80, shooterSubsystem));

// temp climber controls
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
package org.jmhsrobotics.frc2024.autoCommands;
// package org.jmhsrobotics.frc2024.autoCommands;

import org.jmhsrobotics.frc2024.subsystems.intake.IntakeSubsystem;
import org.jmhsrobotics.frc2024.subsystems.intake.commands.IntakeCommand;
import org.jmhsrobotics.frc2024.subsystems.shooter.ShooterSubsystem;
import org.jmhsrobotics.frc2024.subsystems.shooter.commands.ShooterCommand;
// import org.jmhsrobotics.frc2024.subsystems.intake.IntakeSubsystem;
// import org.jmhsrobotics.frc2024.subsystems.intake.commands.IntakeCommand;
// import org.jmhsrobotics.frc2024.subsystems.shooter.ShooterSubsystem;
// import org.jmhsrobotics.frc2024.subsystems.shooter.commands.ShooterCommand;

import edu.wpi.first.wpilibj2.command.SequentialCommandGroup;
// import edu.wpi.first.wpilibj2.command.SequentialCommandGroup;

public class FireCommand extends SequentialCommandGroup {
private IntakeSubsystem intakeSubsystem;
private ShooterSubsystem shooterSubsystem;
// public class FireCommand extends SequentialCommandGroup {
// private IntakeSubsystem intakeSubsystem;
// private ShooterSubsystem shooterSubsystem;

public FireCommand(IntakeSubsystem intakeSubsystem, ShooterSubsystem shooterSubsystem) {
this.intakeSubsystem = intakeSubsystem;
this.shooterSubsystem = shooterSubsystem;
// public FireCommand(IntakeSubsystem intakeSubsystem, ShooterSubsystem
// shooterSubsystem) {
// this.intakeSubsystem = intakeSubsystem;
// this.shooterSubsystem = shooterSubsystem;

addCommands(new ShooterCommand(1, this.shooterSubsystem),
new IntakeCommand(1, this.intakeSubsystem).withTimeout(1));
}
// addCommands(new ShooterCommand(1, this.shooterSubsystem),
// new IntakeCommand(1, this.intakeSubsystem).withTimeout(1));
// }

}
// }
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package org.jmhsrobotics.frc2024.subsystems.intake.commands;

import org.jmhsrobotics.frc2024.subsystems.intake.IntakeSubsystem;
import org.jmhsrobotics.frc2024.subsystems.shooter.ShooterSubsystem;

import edu.wpi.first.wpilibj2.command.Command;

public class IntakeCommand extends Command {

private IntakeSubsystem intakeSubsystem;
private ShooterSubsystem shooterSubsystem;

private double speed;

public IntakeCommand(double speed, IntakeSubsystem intakeSubsystem) {
public IntakeCommand(double speed, IntakeSubsystem intakeSubsystem, ShooterSubsystem shooterSubsystem) {
this.speed = speed;
this.intakeSubsystem = intakeSubsystem;
this.shooterSubsystem = shooterSubsystem;

addRequirements(this.intakeSubsystem);
}
Expand All @@ -25,6 +28,7 @@ public void initialize() {
@Override
public void execute() {
this.intakeSubsystem.set(this.speed);
this.shooterSubsystem.setSpeed(-0.1);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package org.jmhsrobotics.frc2024.subsystems.shooter;

import org.jmhsrobotics.frc2024.Constants;
import org.jmhsrobotics.warcore.rev.RevEncoderSimWrapper;

import com.revrobotics.CANSparkMax;
import com.revrobotics.RelativeEncoder;
import com.revrobotics.CANSparkBase.IdleMode;
import com.revrobotics.CANSparkLowLevel.MotorType;

import edu.wpi.first.math.MathUtil;
import edu.wpi.first.math.controller.PIDController;
import edu.wpi.first.math.system.plant.DCMotor;
import edu.wpi.first.wpilibj.RobotBase;
import edu.wpi.first.wpilibj.simulation.FlywheelSim;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj2.command.SubsystemBase;

public class ShooterPIDSubsystem extends SubsystemBase {
private CANSparkMax topFlywheel = new CANSparkMax(Constants.CAN.kShooterTopId, MotorType.kBrushless);
private CANSparkMax bottomFlywheel = new CANSparkMax(Constants.CAN.kShooterBottomId, MotorType.kBrushless);;
private RelativeEncoder topEncoder;
private RelativeEncoder bottomEncoder;
private PIDController shooterPID;
private double speed;

// private double speed;

public ShooterPIDSubsystem() {
// Initializes motor(s)
initializeMotors();
if (RobotBase.isSimulation()) {
initSim();
}
}

private void initializeMotors() {
this.topFlywheel.setIdleMode(IdleMode.kCoast);
this.topFlywheel.setSmartCurrentLimit(20);
this.topFlywheel.setOpenLoopRampRate(.5);
this.topEncoder = topFlywheel.getEncoder();

this.bottomFlywheel.setIdleMode(IdleMode.kCoast);
this.bottomFlywheel.setSmartCurrentLimit(20);
this.bottomFlywheel.setOpenLoopRampRate(.5);
this.bottomEncoder = bottomFlywheel.getEncoder();

this.bottomFlywheel.follow(topFlywheel);

shooterPID = new PIDController(.004, 0, 0);
shooterPID.setSetpoint(speed);
SmartDashboard.putNumber("shooter/goal", 0);
SmartDashboard.putNumber("shooter/P", shooterPID.getP());
SmartDashboard.putNumber("shooter/I", shooterPID.getI());
SmartDashboard.putNumber("shooter/D", shooterPID.getD());

}

@Override
public void periodic() {
SmartDashboard.putNumber("shooter/topRPM", getRPM());
SmartDashboard.putNumber("shooter/bottomRPM", bottomEncoder.getVelocity());
double PIDOut = shooterPID.calculate(getRPM());
PIDOut = MathUtil.clamp(PIDOut, -.1, 6);
setVolt(PIDOut);
SmartDashboard.putNumber("shooter/PIDOut", PIDOut);
setGoal(SmartDashboard.getNumber("shooter/goal", 0));
shooterPID.setP(SmartDashboard.getNumber("shooter/P", 0));
shooterPID.setI(SmartDashboard.getNumber("shooter/I", 0));
shooterPID.setD(SmartDashboard.getNumber("shooter/D", 0));

}

public double getRPM() {

return topEncoder.getVelocity();
}

public void setGoal(double goal) {
shooterPID.setSetpoint(goal);
}

public boolean atGoal() {
return shooterPID.atSetpoint();
}

public void setSpeed(double speed) {
this.topFlywheel.set(speed);
}

public void setVolt(double amount) {
this.topFlywheel.setVoltage(amount);
}

FlywheelSim flywheelSim;
RevEncoderSimWrapper encSim;
public void initSim() {
flywheelSim = new FlywheelSim(DCMotor.getNEO(1), 1, 1);
encSim = RevEncoderSimWrapper.create(topFlywheel);
}

@Override
public void simulationPeriodic() {
double motorVolts = MathUtil.clamp(topFlywheel.get() * 12, -12, 12);
flywheelSim.setInputVoltage(motorVolts);
flywheelSim.update(Constants.ksimDtSec);
encSim.setVelocity(flywheelSim.getAngularVelocityRPM());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class ShooterSubsystem extends SubsystemBase {
private CANSparkMax bottomFlywheel = new CANSparkMax(Constants.CAN.kShooterBottomId, MotorType.kBrushless);;
private RelativeEncoder topEncoder;
private RelativeEncoder bottomEncoder;
private double goal;
private double volt;

// private double speed;

Expand All @@ -33,22 +35,30 @@ public ShooterSubsystem() {

private void initializeMotors() {
this.topFlywheel.setIdleMode(IdleMode.kCoast);
this.topFlywheel.setSmartCurrentLimit(20);
this.topFlywheel.setSmartCurrentLimit(35);
this.topFlywheel.setOpenLoopRampRate(.5);
this.topEncoder = topFlywheel.getEncoder();

this.bottomFlywheel.setIdleMode(IdleMode.kCoast);
this.bottomFlywheel.setSmartCurrentLimit(20);
this.bottomFlywheel.setSmartCurrentLimit(35);
this.bottomFlywheel.setOpenLoopRampRate(.5);
this.bottomEncoder = bottomFlywheel.getEncoder();

this.bottomFlywheel.follow(topFlywheel);

SmartDashboard.putNumber("shooter/goal", 0);
SmartDashboard.putNumber("shooter/volt", 5.5);
}

@Override
public void periodic() {
SmartDashboard.putNumber("shooter/topRPM", getRPM());
SmartDashboard.putNumber("shooter/bottomRPM", bottomEncoder.getVelocity());
goal = SmartDashboard.getNumber("shooter/goal", 0);
volt = SmartDashboard.getNumber("shooter/volt", 0);
if (getRPM() < goal) {
setVolt(volt);
}
}

public double getRPM() {
Expand All @@ -60,6 +70,10 @@ public void setSpeed(double speed) {
this.topFlywheel.set(speed);
}

public void setVolt(double amount) {
this.topFlywheel.setVoltage(amount);
}

FlywheelSim flywheelSim;
RevEncoderSimWrapper encSim;
public void initSim() {
Expand Down

0 comments on commit 076789c

Please sign in to comment.