Skip to content

Commit

Permalink
gamepiece vision tuning and also climber!
Browse files Browse the repository at this point in the history
  • Loading branch information
shinthebinn committed Mar 12, 2024
1 parent 30fb879 commit 4bff607
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 25 deletions.
2 changes: 2 additions & 0 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ public void teleopInit() {
if (autonomousCommand != null) {
autonomousCommand.cancel();
}

robotContainer.arm.setPosition(5);
}

/** This function is called periodically during operator control. */
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package frc.robot;

import static frc.robot.constants.Constants.tuningMode;
import static frc.robot.constants.Constants.OperatorConstants.*;

import frc.robot.constants.Constants;
Expand Down Expand Up @@ -32,6 +31,7 @@
import frc.robot.commands.vision.GamePieceVision;

import edu.wpi.first.wpilibj.DriverStation;
import edu.wpi.first.wpilibj.Relay.Value;
import edu.wpi.first.wpilibj.shuffleboard.BuiltInWidgets;
import edu.wpi.first.wpilibj.shuffleboard.SendableCameraWrapper;
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
Expand Down Expand Up @@ -166,7 +166,7 @@ private void configureBindings() {
// right bumper -> rotate to speaker apriltag
// driverController.rightBumper().whileTrue(new AprilTagVision(vision, swerve));
// left bumper -> rotate to note
driverController.leftBumper().onTrue(new GamePieceVision(vision, swerve));
driverController.leftBumper().whileTrue(new GamePieceVision(vision, swerve));
driverController.a().onTrue(teleopSwerve.toggleFieldRelative());
// b -> trap/climb align maybe?
driverController.x().whileTrue(new XStance(swerve));
Expand Down Expand Up @@ -197,7 +197,7 @@ private void configureBindings() {
//
// When in tuning mode, create multiple testing options on shuffleboard as well as bind commands to a unique
// 'testing' controller
if (tuningMode) {
if (Constants.tuningMode) {
var indexSpeedEntry = Shuffleboard.getTab("Test").add("Index Speed", 0)
.withWidget(BuiltInWidgets.kNumberSlider)
.withProperties(Map.of("min", -1, "max", 1)).getEntry();
Expand Down Expand Up @@ -228,6 +228,10 @@ private void configureBindings() {

testController.leftStick().whileTrue(new SetIntakeSpeed(intake, -IntakeConstants.intakeSpeed, true));
testController.rightStick().whileTrue(new ManualArmControl(arm, testController::getLeftY));

testController.povDown().onTrue(Commands.runOnce(() -> arm.setClimberRelay(Value.kForward), arm));
testController.povUp().onTrue(Commands.runOnce(() -> arm.setClimberRelay(Value.kReverse), arm));
testController.povLeft().onTrue(Commands.runOnce(() -> arm.setClimberRelay(Value.kOff), arm));
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/main/java/frc/robot/commands/intake/SetIntakeSpeed.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ public SetIntakeSpeed(Intake intake, boolean isIndexing) {
public void initialize() {
// Run motor only if we are either indexing or don't detect a note. Or, if we are intaking (not indexing) and we
// detect a note, don't run
if (isIndexing || !intake.detectNote())
intake.setMotorSpeed(speed);
if (isIndexing || !intake.isHoldingNote())
;
intake.setMotorSpeed(speed);
}

// Called every time the scheduler runs while the command is scheduled.
Expand All @@ -60,6 +61,6 @@ public void end(boolean interrupted) {
public boolean isFinished() {
// If we are intaking and we detect a note, cancel automatically. If we are indexing, the command will only be
// canceled on interrupt
return (!isIndexing && intake.detectNote());
return (!isIndexing && intake.inputs.noteSensor);
}
}
30 changes: 20 additions & 10 deletions src/main/java/frc/robot/commands/vision/GamePieceVision.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import frc.robot.subsystems.Swerve;
import frc.robot.subsystems.Vision;

import edu.wpi.first.math.MathUtil;
import edu.wpi.first.math.controller.PIDController;
import edu.wpi.first.math.geometry.Translation2d;
import edu.wpi.first.wpilibj2.command.Command;

Expand All @@ -18,6 +20,8 @@ public class GamePieceVision extends Command {
private Swerve swerve;
private double robotRotate_radps;
private boolean isAligned;
private PIDController pidController = new PIDController(VisionConstants.gamePieceRotateKp, 0,
VisionConstants.gamePieceRotateKd);

/** Creates a new GamePieceVision. */
public GamePieceVision(Vision vision, Swerve swerve) {
Expand All @@ -43,19 +47,25 @@ public void execute() {
Logger.recordOutput("GamePieceVision/isAligned", isAligned);

// When we see a ground GamePiece, we will rotate to it
if (vision.pieceInputs.crosshairToTargetErrorX_rad < -VisionConstants.crosshairGamePieceBoundRotateX_rad) {
robotRotate_radps = VisionConstants.gamePieceRotateKp
* vision.pieceInputs.crosshairToTargetErrorX_rad
- VisionConstants.gamePieceRotateKd;
} else if (VisionConstants.crosshairGamePieceBoundRotateX_rad < vision.pieceInputs.crosshairToTargetErrorX_rad) {
robotRotate_radps = VisionConstants.gamePieceRotateKp
* vision.pieceInputs.crosshairToTargetErrorX_rad
+ VisionConstants.gamePieceRotateKd;
// if (vision.pieceInputs.crosshairToTargetErrorX_rad < -VisionConstants.crosshairGamePieceBoundRotateX_rad) {
// robotRotate_radps = VisionConstants.gamePieceRotateKp
// * vision.pieceInputs.crosshairToTargetErrorX_rad
// - VisionConstants.gamePieceRotateKd;
// } else if (VisionConstants.crosshairGamePieceBoundRotateX_rad < vision.pieceInputs.crosshairToTargetErrorX_rad) {
// robotRotate_radps = VisionConstants.gamePieceRotateKp
// * vision.pieceInputs.crosshairToTargetErrorX_rad
// + VisionConstants.gamePieceRotateKd;
// }
// robotRotate_radps *= -1; // Rotate opposite of error
if (!MathUtil.isNear(0, vision.pieceInputs.crosshairToTargetErrorX_rad,
VisionConstants.crosshairGamePieceBoundRotateX_rad)) {
robotRotate_radps = pidController.calculate(vision.pieceInputs.crosshairToTargetErrorX_rad, 0);
} else {
robotRotate_radps = 0;
}
robotRotate_radps *= -1; // Rotate opposite of error

// Generate a continuously updated rotation to GamePiece
System.out.println("Swerve --> GamePiece");
Logger.recordOutput("Vision/targetRotation", robotRotate_radps);
swerve.drive(new Translation2d(0, 0), robotRotate_radps, false); // TELL DRIVE THAT THEY ARE ALWAYS ROBOT ORIENTED
// WHEN ALIGN TO NOTE
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/frc/robot/constants/VisionConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ public class VisionConstants {
public static final double poseError_m = 1; // comparing visionPose to pose
public static final double botpose_fieldOffsetX_m = 0.025; // realife offset to pathplanner app
/* ObjectDetectionVision */
public static final double gamePieceRotateKp = 1.2;
public static final double gamePieceRotateKd = 0.34;
public static final double gamePieceRotateKp = 1.75;
public static final double gamePieceRotateKd = 1.4;

public static final double AprilTagRotateKp = 1.2;
public static final double AprilTagRotateKd = 0.34;

public static final double crosshairGamePieceBoundRotateX_rad = Math.toRadians(1.0);
public static final double crosshairGamePieceBoundRotateX_rad = Math.toRadians(1.5);

public static final int redSpeakerTag = 4;
public static final int blueSpeakerTag = 7;
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/frc/robot/io/PieceVisionIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static class PieceVisionIOInputs {
}

// Network table declarations
private NetworkTable table = NetworkTableInstance.getDefault().getTable("limelight-gp");
private NetworkTable table = NetworkTableInstance.getDefault().getTable("limelight-gpv");

private NetworkTableEntry pipelineEntry = table.getEntry("pipeline");
private NetworkTableEntry tvEntry = table.getEntry("tv");
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/frc/robot/subsystems/Arm.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import edu.wpi.first.math.MathUtil;
import edu.wpi.first.math.controller.ArmFeedforward;
import edu.wpi.first.math.util.Units;
import edu.wpi.first.wpilibj.Relay;
import edu.wpi.first.wpilibj2.command.SubsystemBase;

import com.revrobotics.AbsoluteEncoder;
Expand Down Expand Up @@ -36,6 +37,8 @@ public class Arm extends SubsystemBase {

private ArmFeedforward feedforwardController = new ArmFeedforward(kS, kG, kV, kA);

private Relay climberRelay = new Relay(0);

@Getter
@AutoLogOutput
private double targetPosition_deg = 0;
Expand Down Expand Up @@ -150,6 +153,11 @@ public void setMotorVoltage(double voltage_V) {
feedforwardController.calculate(Units.degreesToRadians(inputs.shaftPosition_deg), 0));
}

public void setClimberRelay(Relay.Value value) {
climberRelay.set(value);
Logger.recordOutput("Arm/relaySetting", value);
}

public void stop() {
pidController.setReference(0, ControlType.kDutyCycle, 0,
feedforwardController.calculate(Units.degreesToRadians(inputs.shaftPosition_deg), 0));
Expand Down
22 changes: 17 additions & 5 deletions src/main/java/frc/robot/subsystems/Intake.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,24 @@
import com.revrobotics.CANSparkMax;

import org.littletonrobotics.junction.AutoLog;
import org.littletonrobotics.junction.AutoLogOutput;
import org.littletonrobotics.junction.Logger;

import lombok.Getter;
import lombok.Setter;

public class Intake extends SubsystemBase {
private final CANSparkMax motor = new CANSparkMax(motorId, MotorType.kBrushless);

private final DigitalInput noteSensor = new DigitalInput(sensorId);

@Getter
@Setter
@AutoLogOutput
private boolean holdingNote = false;

private boolean cachedNoteSensor = false;

public Intake() {
motor.restoreFactoryDefaults();
motor.setIdleMode(IdleMode.kBrake);
Expand All @@ -30,6 +41,12 @@ public Intake() {
public void periodic() {
updateInputs(inputs);
Logger.processInputs(getName(), inputs);

if ((inputs.noteSensor != cachedNoteSensor) && inputs.noteSensor) {
holdingNote = !holdingNote;
}

cachedNoteSensor = inputs.noteSensor;
}

public void setMotorSpeed(double speed) {
Expand All @@ -56,11 +73,6 @@ public void updateInputs(IntakeIOInputs inputs) {
inputs.noteSensor = !noteSensor.get();
}

public boolean detectNote() {
return inputs.noteSensor;

}

public void stopMotor() {
motor.stopMotor();
}
Expand Down

0 comments on commit 4bff607

Please sign in to comment.