Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/pre-main' into unit_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jhhbrown1 committed Feb 8, 2025
2 parents e25552b + f0f8260 commit 3ef9021
Show file tree
Hide file tree
Showing 7 changed files with 723 additions and 8 deletions.
68 changes: 68 additions & 0 deletions src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,38 @@
import edu.wpi.first.math.util.Units;

public class Constants {
public static final class AlgaeConstants {
// FLYWHEEL IS 550
// OTHER IS NORMAL NEO

public static final int kFlywheelMotorPort = 90;
public static final int kGrabberAnglePort = 3;
public static final boolean kFlywheelInvert = false;
public static final boolean kGrabberAngleInvert = false;

public static final int kSmartCurrentLimit = 50;
public static final int kPeakCurrentDurationMillis = 100;

public static final int k550SmartCurrentLimit = 15;

public static final double kCurrentToStop = 20;
public static final double kTimeOverCurrentToStop = .01;

public static final double kP = 0.5;
public static final double kI = 0.0;
public static final double kD = 0;
}

public static final class CheeseStickConstants {
public static final int kServoPort = 0;
public static final int kMaxRotation = 270;
}

public static final class ClimberConstants {
public static final int kClimberMotorPort = -1; // TODO: Add actual motor ID
public static final double kSpeed = 0.5;
}

public static final class ControllerConstants {
public static final int kDriverControllerPort = 0;
public static final int kOperatorControllerPort = 1;
Expand Down Expand Up @@ -119,6 +151,42 @@ public static final class DriveConstants {

}

public static final class ElevatorConstants {
public static final double kFF = 0.00008040000102482736; // Feedforward Constant
public static final int kElevatorMotorPort = 45;
public static final int kSmartCurrentLimit = 60;
public static final int kSecondaryCurrentLimit = 70;
public static final double kMinOutput = -1;
public static final double kMaxOutput = 1;
public static final double kP = 5;
public static final double kI = 0;
public static final double kD = 0;
public static final double kTolerance = 1;
public static final int kMaxExtension = 250;
public static final double kLevelOneHeight = Units.inchesToMeters(41 - 24);
public static final double kLevelTwoHeight = kLevelOneHeight; // same as level 1
public static final double kLevelThreeHeight = Units.inchesToMeters(60 - 24);
public static final double kLevelFourHeight = Units.inchesToMeters(90 - 24);
public static final double kCoralStationHeight = 0;
}

public static final class WristConstants {
public static final int kWristMotorPort = 1; /* 60 */
public static final int kSmartCurrentLimit = 20;
public static final int kSecondaryCurrentLimit = 20;

// Make sure these are tuned (can do with SysId)
public static final double kP = 0.09;
public static final double kI = 0.0;
public static final double kD = 0;
public static final double kS = 0;
public static final double kG = 0;
public static final double kV = 0.11;
public static final double kA = 0.009;

public static final double kTolerance = 0;
}

/**
* The {@code AprilTagFieldLayout}.
*/
Expand Down
86 changes: 78 additions & 8 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@

import static edu.wpi.first.wpilibj2.command.Commands.*;
import static frc.robot.Constants.*;
import static frc.robot.Constants.AlgaeConstants.*;
import static frc.robot.Constants.ClimberConstants.*;
import static frc.robot.Constants.ControllerConstants.*;
import static frc.robot.Constants.ElevatorConstants.*;
import static frc.robot.Constants.RobotConstants.*;
import static frc.robot.Constants.WristConstants.*;
import static frc.robot.subsystems.PoseEstimationSubsystem.*;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.DoubleSupplier;

Expand All @@ -18,32 +24,50 @@
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.geometry.Transform2d;
import edu.wpi.first.math.kinematics.ChassisSpeeds;
import edu.wpi.first.math.util.Units;
import edu.wpi.first.wpilibj.DataLogManager;
import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.PowerDistribution;
import edu.wpi.first.wpilibj.RobotBase;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.Mechanism2d;
import edu.wpi.first.wpilibj.smartdashboard.MechanismLigament2d;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj.util.Color;
import edu.wpi.first.wpilibj.util.Color8Bit;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.CommandScheduler;
import edu.wpi.first.wpilibj2.command.button.CommandPS4Controller;
import frc.robot.Constants.ControllerConstants;
import edu.wpi.first.wpilibj2.command.button.CommandPS5Controller;
import frc.robot.Constants.ControllerConstants.Button;
import frc.robot.subsystems.AlgaeGrabberSubsystem;
import frc.robot.subsystems.AlgaeGrabberSubsystem.GrabberState;
import frc.robot.subsystems.CheeseStickSubsystem;
import frc.robot.subsystems.ClimberSubsystem;
import frc.robot.subsystems.DriveSubsystem;
import frc.robot.subsystems.ElevatorSubsystem;
import frc.robot.subsystems.PhotonCameraSimulator;
import frc.robot.subsystems.PoseEstimationSubsystem;
import frc.robot.subsystems.VisionSimulator;
import frc.robot.subsystems.WristSubsystem;

public class Robot extends TimedRobot {
private final SendableChooser<Command> m_autoSelector = new SendableChooser<Command>();
private final SendableChooser<Command> m_testSelector = new SendableChooser<Command>();

private Command m_autonomousCommand;
private final Mechanism2d m_mechanism = new Mechanism2d(Units.inchesToMeters(35), Units.inchesToMeters(100));
private final AlgaeGrabberSubsystem m_algaeGrabberSubsystem = new AlgaeGrabberSubsystem();
private final CheeseStickSubsystem m_cheeseStickSubsystem = new CheeseStickSubsystem();
private final ClimberSubsystem m_climberSubsystem = new ClimberSubsystem();
private Command m_testCommand;
private final DriveSubsystem m_driveSubsystem = new DriveSubsystem();
private final CommandPS4Controller m_driverController = new CommandPS4Controller(
ControllerConstants.kDriverControllerPort);
private final ElevatorSubsystem m_elevatorSubsystem = new ElevatorSubsystem(
m_mechanism.getRoot("anchor", Units.inchesToMeters(23), 0));
private final WristSubsystem m_wristSubsystem = new WristSubsystem(m_elevatorSubsystem.getWristMount());
// Changed to PS5
private final CommandPS5Controller m_driverController = new CommandPS5Controller(kDriverControllerPort);
private final CommandPS5Controller m_operatorController = new CommandPS5Controller(kOperatorControllerPort);
private final PowerDistribution m_pdh = new PowerDistribution();
private final VisionSimulator m_visionSimulator = new VisionSimulator(m_driveSubsystem,
pose(kFieldLayout.getFieldLength() / 2, 1.91, 0), 0.01);
Expand All @@ -58,6 +82,10 @@ public class Robot extends TimedRobot {
.addCamera(m_camera2, kRobotToCamera2);

public Robot() {
var dropChute = new MechanismLigament2d("bottom", Units.inchesToMeters(5), 0, 5, new Color8Bit(Color.kBeige));
dropChute.append(new MechanismLigament2d("side", Units.inchesToMeters(12), 90, 5, new Color8Bit(Color.kWhite)));
m_mechanism.getRoot("dropChute", Units.inchesToMeters(28), Units.inchesToMeters(9)).append(dropChute);
SmartDashboard.putData("Superstructure", m_mechanism);
CommandComposer.setSubsystems(m_driveSubsystem, m_poseEstimationSubsystem);

m_autoSelector.addOption("Test DriveSubsystem", m_driveSubsystem.testCommand());
Expand All @@ -73,12 +101,19 @@ public Robot() {
SmartDashboard.putData(CommandScheduler.getInstance());
DataLogManager.start();
DataLogManager.logNetworkTables(true);
URCL.start(
var m = new LinkedHashMap<Integer, String>(Map.of(
10, "FR Drive", 11, "FR Turn", 20, "BR Drive", 21, "BR Turn", 30, "BL Drive", 31, "BL Turn",
40, "FL Drive", 41, "FL Turn"));
m.putAll(
Map.of(
10, "FR Drive", 11, "FR Turn", 20, "BR Drive", 21, "BR Turn", 30, "BL Drive", 31, "BL Turn",
40, "FL Drive", 41, "FL Turn"));
kElevatorMotorPort, "Elevator",
kClimberMotorPort, "Climber Motor", kWristMotorPort, "Wrist Motor", kFlywheelMotorPort,
"Algae Motor"));
URCL.start(m);
DriverStation.startDataLog(DataLogManager.getLog());
bindDriveControls();
bindElevatorControls();
bindWristControls();
}

public void bindDriveControls() {
Expand All @@ -88,7 +123,7 @@ public void bindDriveControls() {
() -> -m_driverController.getLeftX(),
() -> m_driverController.getL2Axis() - m_driverController.getR2Axis(),
m_driverController.getHID()::getSquareButton));

// TODO: Add in joystick rotation
m_driverController.button(Button.kSquare)
.whileTrue(
driveWithAlignmentCommand(
Expand All @@ -98,6 +133,41 @@ public void bindDriveControls() {
new Transform2d(0.5, 0, Rotation2d.fromDegrees(180)), 2));
}

public void bindElevatorControls() {
m_operatorController.circle().onTrue(m_elevatorSubsystem.goToLevelFourCommand());
m_operatorController.triangle().onTrue(m_elevatorSubsystem.goToLevelThreeCommand());
m_operatorController.square().onTrue(m_elevatorSubsystem.goToLevelTwoCommand());
m_operatorController.cross().onTrue(m_elevatorSubsystem.goToLevelOneCommand());
m_operatorController.povLeft().onTrue(m_elevatorSubsystem.goToCoralStationCommand());
// TODO: Add manual movement
}

public void bindAlgaeControls() {
m_operatorController.R1().onTrue(
m_algaeGrabberSubsystem.deployGrabberCommand(GrabberState.DOWN)
.andThen(m_algaeGrabberSubsystem.runFlywheelCommand())); // TODO: Come up after?
m_operatorController.L1().onTrue(
m_algaeGrabberSubsystem.runFlywheelReverseCommand()
.until(m_algaeGrabberSubsystem::checkCurrentOnFlywheel)
.andThen(m_algaeGrabberSubsystem.stopFlywheelCommand()));
}

public void bindWristControls() {
m_driverController.circle().onTrue(m_wristSubsystem.reverseMotor());
m_driverController.square().onTrue(m_wristSubsystem.forwardMotor());
}

public void bindCheeseStickControls() {
// Need to figure out what left and right actually mean
m_operatorController.R2().whileFalse(m_cheeseStickSubsystem.goLeft());
m_operatorController.R2().whileTrue(m_cheeseStickSubsystem.goRight());
}

public void bindClimberControls() {
m_operatorController.L2().whileTrue(m_climberSubsystem.moveForward())
.onFalse(m_climberSubsystem.moveBackward());
}

/**
* Creates a {@code Command} to automatically align the robot to the closest
* {@code AprilTag} while driving the robot with joystick input.
Expand Down
148 changes: 148 additions & 0 deletions src/main/java/frc/robot/subsystems/AlgaeGrabberSubsystem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// 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.subsystems;

import com.revrobotics.spark.SparkBase.ControlType;
import com.revrobotics.spark.SparkBase.PersistMode;
import com.revrobotics.spark.SparkBase.ResetMode;
import com.revrobotics.spark.SparkClosedLoopController;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import com.revrobotics.spark.SparkMax;
import com.revrobotics.spark.config.ClosedLoopConfig.FeedbackSensor;
import com.revrobotics.spark.config.SparkBaseConfig.IdleMode;
import com.revrobotics.spark.config.SparkMaxConfig;

import edu.wpi.first.math.filter.Debouncer;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants.AlgaeConstants;

public class AlgaeGrabberSubsystem extends SubsystemBase {
private final SparkMax m_flywheel;
private final SparkMax m_grabberAngleMotor = new SparkMax(AlgaeConstants.kGrabberAnglePort,
MotorType.kBrushless);
private final SparkClosedLoopController m_grabberClosedLoopController = m_grabberAngleMotor
.getClosedLoopController();

private final Debouncer m_debouncerCurrentLimitStop = new Debouncer(AlgaeConstants.kTimeOverCurrentToStop);

private double m_setVelocity;

public enum GrabberState {
UP,
DOWN
}

public AlgaeGrabberSubsystem() {
m_flywheel = new SparkMax(AlgaeConstants.kFlywheelMotorPort, MotorType.kBrushless);

// Initialize Motors
// applies the inverts and coast mode to the flywheel motors. if you want to
// make a motor spin the other way change it in the AlgaeConstants.k____Invert
// variable
// also applies voltage and current stuff to the motors

var config = new SparkMaxConfig();
config.inverted(AlgaeConstants.kFlywheelInvert).idleMode(IdleMode.kBrake);
config.voltageCompensation(12).smartCurrentLimit(AlgaeConstants.k550SmartCurrentLimit);
m_flywheel.configure(config, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters);

config = new SparkMaxConfig();
config.inverted(AlgaeConstants.kGrabberAngleInvert).idleMode(IdleMode.kBrake);
config.voltageCompensation(12).smartCurrentLimit(AlgaeConstants.kSmartCurrentLimit);
config.closedLoop
.feedbackSensor(FeedbackSensor.kPrimaryEncoder)
.pid(AlgaeConstants.kP, AlgaeConstants.kI, AlgaeConstants.kD);
m_grabberAngleMotor.configure(config, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters);
}

@Override
public void periodic() {
// use this to check what the kCurrentToStop should be
// System.out.println(m_flywheel.getOutputCurrent());
}

public double getVelocity() {
return m_flywheel.getAbsoluteEncoder().getVelocity();
}

/**
* sets the speed for the wheels to grab the Algae balls
*
* @param velocity (double) (-1 to 1) sets m_setVelocity and changes the wheel
* to go that speed using .set from {@link SparkMax}
* @return (void) motor will spin velocity
*/
public void setVelocity(double velocity) {
m_setVelocity = velocity;
m_flywheel.set(m_setVelocity);
}

/**
* checks the current draw on the flywheel motor and will check if it's lower or
* higher than AlgaeConstants.kCurrentToStop using a debouncer
*
* @return (boolean) true -> if the current draw is higher or equal than
* kCurrentToStop
* <p>
* (boolean) false -> otherwise
*/
public boolean checkCurrentOnFlywheel() {
return m_debouncerCurrentLimitStop
.calculate(m_flywheel.getOutputCurrent() >= AlgaeConstants.kCurrentToStop);
}

/**
* command to stop the algae flywheel using the setVelocity method
*
* @return (setVelocity(0)) sets the flywheel velocity to 0
*/
public Command stopFlywheelCommand() {
return runOnce(() -> {
setVelocity(0);
});
}

/**
* command to start the algae flywheel using the setVelocity method
*
* @return (setVelocity(.75)) sets the flywheel velocity to 75%
*/
public Command runFlywheelCommand() {
return runOnce(() -> {
setVelocity(.75);
});
}

/**
* command to reverse the algae flywheel using the setVelocity method
*
* @return (setVelocity(-.75)) sets the flywheel velocity to -75%
*/
public Command runFlywheelReverseCommand() {
return runOnce(() -> {
setVelocity(-.75);
});
}

/**
* deploys the grabber for algae
*
* @param state (enum grabberState) can be UP or DOWN, UP will bring the grabber
* up, DOWN will bring it down
*
* @return moves the whole grabber setup using a PID based on the grabberState
* enum given
*/
public Command deployGrabberCommand(GrabberState state) {
return runOnce(() -> {
if (GrabberState.DOWN == state) {
m_grabberClosedLoopController.setReference(2, ControlType.kPosition);
} else if (GrabberState.UP == state) {
m_grabberClosedLoopController.setReference(0, ControlType.kPosition);
}
});
}
}
Loading

0 comments on commit 3ef9021

Please sign in to comment.