From 21aae1f54f22e94f14d02d93eb2ef25195838d58 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Fri, 22 Mar 2024 20:43:43 -0700 Subject: [PATCH 01/20] a command to autoMATICALLY goes and intakes note --- .../java/org/carlmontrobotics/Constants.java | 13 +++-- .../commands/AlignToApriltag.java | 3 +- .../commands/AlignToNote.java | 2 +- .../commands/AutoMATICALLYGetNote.java | 57 +++++++++++++++++++ .../commands/RotateToFieldRelativeAngle.java | 2 +- .../commands/TeleopDrive.java | 2 +- .../subsystems/Drivetrain.java | 2 +- .../subsystems/IntakeShooter.java | 7 +++ .../subsystems/Limelight.java | 12 +++- 9 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java create mode 100644 src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index d11fd880..46a25b80 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -24,7 +24,7 @@ public final class Constants { public static final double g = 9.81; //meters per second squared - public static final class Drivetrain { + public static final class Drivetrainc { //#region Subsystem Constants @@ -149,14 +149,14 @@ public static final class Drivetrain { //#endregion } - public static final class Arm { + public static final class Armc { } - public static final class IntakeShooter { + public static final class IntakeShooterc { } - public static final class Limelight { - public static final String INTAKE_LL_NAME = "intake-limelight"; - public static final String SHOOTER_LL_NAME = "shooter-limelight"; + public static final class Limelightc { + public static final String INTAKE_LL_NAME = "limelight-intake"; + public static final String SHOOTER_LL_NAME = "limelight-shooter"; public static final double ERROR_TOLERANCE = 0.1; public static final double HORIZONTAL_FOV_DEG = 0; @@ -164,6 +164,7 @@ public static final class Limelight { public static final double MOUNT_ANGLE_DEG = 46.2; //23.228 public static final double HEIGHT_FROM_GROUND_METERS = Units.inchesToMeters(9); //16.6 public static final double ARM_TO_OUTTAKE_OFFSET_DEG= 115; + public static final double NOTE_HEIGHT = Units.inchesToMeters(2); public static final class Apriltag { public static final int RED_SPEAKER_CENTER_TAG_ID = 4; public static final int BLUE_SPEAKER_CENTER_TAG_ID = 7; diff --git a/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java b/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java index b5d3e6de..c54475c3 100644 --- a/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java +++ b/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java @@ -4,7 +4,7 @@ package org.carlmontrobotics.commands; -import static org.carlmontrobotics.Constants.Limelight.*; +import static org.carlmontrobotics.Constants.Limelightc.*; import org.carlmontrobotics.subsystems.Drivetrain; import edu.wpi.first.math.geometry.Rotation2d; import edu.wpi.first.wpilibj2.command.ProxyCommand; @@ -17,5 +17,6 @@ public AlignToApriltag(Drivetrain dt) { Rotation2d fieldOrientedTargetAngle = Rotation2d.fromDegrees(LimelightHelpers.getTX(SHOOTER_LL_NAME)).plus(Rotation2d.fromDegrees(dt.getHeading())); return new RotateToFieldRelativeAngle(fieldOrientedTargetAngle, dt); }); + addRequirements(dt); } } \ No newline at end of file diff --git a/src/main/java/org/carlmontrobotics/commands/AlignToNote.java b/src/main/java/org/carlmontrobotics/commands/AlignToNote.java index 301ae6dc..db5ba9f5 100644 --- a/src/main/java/org/carlmontrobotics/commands/AlignToNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AlignToNote.java @@ -4,7 +4,7 @@ package org.carlmontrobotics.commands; -import static org.carlmontrobotics.Constants.Limelight.*; +import static org.carlmontrobotics.Constants.Limelightc.*; import org.carlmontrobotics.subsystems.Drivetrain; import edu.wpi.first.math.geometry.Rotation2d; import edu.wpi.first.wpilibj2.command.ProxyCommand; diff --git a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java new file mode 100644 index 00000000..2d11dc95 --- /dev/null +++ b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java @@ -0,0 +1,57 @@ +// 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 org.carlmontrobotics.commands; + +import org.carlmontrobotics.Constants.*; +import org.carlmontrobotics.subsystems.*; + +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.util.Units; +import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.InstantCommand; +import edu.wpi.first.wpilibj2.command.ParallelCommandGroup; +import edu.wpi.first.wpilibj2.command.ParallelRaceGroup; +import edu.wpi.first.wpilibj2.command.ProxyCommand; +import edu.wpi.first.wpilibj2.command.SequentialCommandGroup; +import edu.wpi.first.wpilibj2.command.WaitCommand; + +public class AutoMATICALLYGetNote extends Command { + /** Creates a new AutoMATICALLYGetNote. */ + private Drivetrain dt; + private IntakeShooter effector; + private Limelight limelight; + + public AutoMATICALLYGetNote(Drivetrain dt, IntakeShooter effector) { + addRequirements(this.dt = dt); + addRequirements(this.effector = effector); + // Use addRequirements() here to declare subsystem dependencies. + } + + @Override + public void initialize() { + //new Intake().finallyDo(()->{this.end(false);}); + dt.setFieldOriented(false); + } + + @Override + public void execute() { + double radErr = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); + double distErr = limelight.getDistanceToNote(); //meters + dt.drive(Math.max(distErr*2, .5),0,Math.max(radErr*2,.5)); + //180deg is about 6.2 rad/sec, min is .5rad/sec + } + + // Called once the command ends or is interrupted. + @Override + public void end(boolean interrupted) { + dt.setFieldOriented(true); + } + + // Returns true when the command should end. + @Override + public boolean isFinished() { + return false; + } +} diff --git a/src/main/java/org/carlmontrobotics/commands/RotateToFieldRelativeAngle.java b/src/main/java/org/carlmontrobotics/commands/RotateToFieldRelativeAngle.java index 98dc1fd6..d37e6017 100644 --- a/src/main/java/org/carlmontrobotics/commands/RotateToFieldRelativeAngle.java +++ b/src/main/java/org/carlmontrobotics/commands/RotateToFieldRelativeAngle.java @@ -8,7 +8,7 @@ import edu.wpi.first.util.sendable.SendableRegistry; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.Command; -import static org.carlmontrobotics.Constants.Drivetrain.*; +import static org.carlmontrobotics.Constants.Drivetrainc.*; public class RotateToFieldRelativeAngle extends Command { diff --git a/src/main/java/org/carlmontrobotics/commands/TeleopDrive.java b/src/main/java/org/carlmontrobotics/commands/TeleopDrive.java index 098c5581..900609e8 100644 --- a/src/main/java/org/carlmontrobotics/commands/TeleopDrive.java +++ b/src/main/java/org/carlmontrobotics/commands/TeleopDrive.java @@ -1,6 +1,6 @@ package org.carlmontrobotics.commands; -import static org.carlmontrobotics.Constants.Drivetrain.*; +import static org.carlmontrobotics.Constants.Drivetrainc.*; import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; diff --git a/src/main/java/org/carlmontrobotics/subsystems/Drivetrain.java b/src/main/java/org/carlmontrobotics/subsystems/Drivetrain.java index fdca39b4..fb04c804 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Drivetrain.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Drivetrain.java @@ -1,6 +1,6 @@ package org.carlmontrobotics.subsystems; -import static org.carlmontrobotics.Constants.Drivetrain.*; +import static org.carlmontrobotics.Constants.Drivetrainc.*; import java.util.Arrays; import java.util.function.Supplier; diff --git a/src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java b/src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java new file mode 100644 index 00000000..37efb132 --- /dev/null +++ b/src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java @@ -0,0 +1,7 @@ +package org.carlmontrobotics.subsystems; + +import edu.wpi.first.wpilibj2.command.SubsystemBase; + +public class IntakeShooter extends SubsystemBase{ + +} diff --git a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java index 20c7cf39..89f8b217 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java @@ -1,7 +1,7 @@ package org.carlmontrobotics.subsystems; -import static org.carlmontrobotics.Constants.Limelight.*; -import static org.carlmontrobotics.Constants.Limelight.Apriltag.*; +import static org.carlmontrobotics.Constants.Limelightc.*; +import static org.carlmontrobotics.Constants.Limelightc.Apriltag.*; import edu.wpi.first.math.MathUtil; @@ -75,6 +75,14 @@ public double getDistanceToTargetSpeaker(){ } } + public double getDistanceToNote(){ + Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(INTAKE_LL_NAME))); + double distance = (NOTE_HEIGHT - HEIGHT_FROM_GROUND_METERS) / angleToGoal.getTan(); + SmartDashboard.putNumber("limelight distance to note", distance); + return distance; + } + + // public Pose3d getTargetPose() { // double[] poseArray = LimelightHelpers.getLimelightNTDoubleArray(SHOOTER_LL_NAME, "targetpose_robotspace"); // return LimelightHelpers.toPose3D(poseArray); From a6e08a8bfa0766da81974af4cdbae3118d305662 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:02:39 -0700 Subject: [PATCH 02/20] automatic get note math --- src/main/java/org/carlmontrobotics/RobotContainer.java | 3 ++- .../org/carlmontrobotics/commands/AutoMATICALLYGetNote.java | 4 +++- src/main/java/org/carlmontrobotics/subsystems/Limelight.java | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/RobotContainer.java b/src/main/java/org/carlmontrobotics/RobotContainer.java index 1c385a8c..eb5c28a9 100644 --- a/src/main/java/org/carlmontrobotics/RobotContainer.java +++ b/src/main/java/org/carlmontrobotics/RobotContainer.java @@ -77,7 +77,8 @@ private void setDefaultCommands() { } private void setBindingsDriver() { new JoystickButton(driverController, 1).onTrue(new AlignToApriltag(drivetrain)); //button A - new JoystickButton(driverController, 2).whileTrue(new AlignToNote(drivetrain)); //button b? + new JoystickButton(driverController, 2).onTrue(new AlignToNote(drivetrain)); //button b? + new JoystickButton(driverController, 2).whileTrue(new AlignToNote(drivetrain)); //button x? // reset field orientation?? // new JoystickButton(driverController, Driver.resetFieldOrientationButton).onTrue( // new InstantCommand(drivetrain::resetFieldOrientation)); diff --git a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java index 2d11dc95..ad4e6a7e 100644 --- a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java @@ -39,7 +39,9 @@ public void initialize() { public void execute() { double radErr = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); double distErr = limelight.getDistanceToNote(); //meters - dt.drive(Math.max(distErr*2, .5),0,Math.max(radErr*2,.5)); + double forwardErr = distErr * Math.cos(radErr); + double strafeErr = distErr * Math.sin(radErr); + dt.drive(Math.max(forwardErr*2, .5), Math.max(strafeErr*2, .5), Math.max(radErr*2,.5)); //180deg is about 6.2 rad/sec, min is .5rad/sec } diff --git a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java index 89f8b217..450231dd 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java @@ -82,7 +82,6 @@ public double getDistanceToNote(){ return distance; } - // public Pose3d getTargetPose() { // double[] poseArray = LimelightHelpers.getLimelightNTDoubleArray(SHOOTER_LL_NAME, "targetpose_robotspace"); // return LimelightHelpers.toPose3D(poseArray); From a4f0e51e6ec0b268431fe7ddca26d2aa035a6066 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:11:04 -0700 Subject: [PATCH 03/20] constants --- src/main/java/org/carlmontrobotics/Constants.java | 6 ++++-- .../java/org/carlmontrobotics/subsystems/Limelight.java | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index 46a25b80..4e819f8f 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -161,8 +161,10 @@ public static final class Limelightc { public static final double ERROR_TOLERANCE = 0.1; public static final double HORIZONTAL_FOV_DEG = 0; public static final double RESOLUTION_WIDTH = 640; - public static final double MOUNT_ANGLE_DEG = 46.2; //23.228 - public static final double HEIGHT_FROM_GROUND_METERS = Units.inchesToMeters(9); //16.6 + public static final double MOUNT_ANGLE_DEG_SHOOTER = 46.2; //23.228 + public static final double MOUNT_ANGLE_DEG_INTAKE = 46.2; //23.228 + public static final double HEIGHT_FROM_GROUND_METERS_SHOOTER = Units.inchesToMeters(56); //16.6 + public static final double HEIGHT_FROM_GROUND_METERS_INTAKE = Units.inchesToMeters(56); //16.6 public static final double ARM_TO_OUTTAKE_OFFSET_DEG= 115; public static final double NOTE_HEIGHT = Units.inchesToMeters(2); public static final class Apriltag { diff --git a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java index 450231dd..95cda1ca 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java @@ -63,8 +63,8 @@ public Pose2d getCurrentPose(){ public double getDistanceToTargetSpeaker(){ if (LimelightHelpers.getFiducialID(SHOOTER_LL_NAME) == RED_SPEAKER_CENTER_TAG_ID || LimelightHelpers.getFiducialID(SHOOTER_LL_NAME) == BLUE_SPEAKER_CENTER_TAG_ID){ - Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(SHOOTER_LL_NAME))); - double distance = (SPEAKER_CENTER_HEIGHT_METERS - HEIGHT_FROM_GROUND_METERS) / angleToGoal.getTan(); + Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG_SHOOTER).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(SHOOTER_LL_NAME))); + double distance = (SPEAKER_CENTER_HEIGHT_METERS - HEIGHT_FROM_GROUND_METERS_SHOOTER) / angleToGoal.getTan(); SmartDashboard.putNumber("limelight distance", distance); return distance; } @@ -76,8 +76,8 @@ public double getDistanceToTargetSpeaker(){ } public double getDistanceToNote(){ - Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(INTAKE_LL_NAME))); - double distance = (NOTE_HEIGHT - HEIGHT_FROM_GROUND_METERS) / angleToGoal.getTan(); + Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG_INTAKE).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(INTAKE_LL_NAME))); + double distance = (NOTE_HEIGHT - HEIGHT_FROM_GROUND_METERS_INTAKE) / angleToGoal.getTan(); SmartDashboard.putNumber("limelight distance to note", distance); return distance; } From cd3d9f54297c56936ec2ed5a0b377cfc594252f6 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:31:09 -0700 Subject: [PATCH 04/20] constants --- src/main/java/org/carlmontrobotics/Constants.java | 4 ++-- src/main/java/org/carlmontrobotics/commands/AlignToNote.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index 4e819f8f..43be980c 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -161,8 +161,8 @@ public static final class Limelightc { public static final double ERROR_TOLERANCE = 0.1; public static final double HORIZONTAL_FOV_DEG = 0; public static final double RESOLUTION_WIDTH = 640; - public static final double MOUNT_ANGLE_DEG_SHOOTER = 46.2; //23.228 - public static final double MOUNT_ANGLE_DEG_INTAKE = 46.2; //23.228 + public static final double MOUNT_ANGLE_DEG_SHOOTER = 25; //23.228 + public static final double MOUNT_ANGLE_DEG_INTAKE = 17.5 + 0; //23.228 public static final double HEIGHT_FROM_GROUND_METERS_SHOOTER = Units.inchesToMeters(56); //16.6 public static final double HEIGHT_FROM_GROUND_METERS_INTAKE = Units.inchesToMeters(56); //16.6 public static final double ARM_TO_OUTTAKE_OFFSET_DEG= 115; diff --git a/src/main/java/org/carlmontrobotics/commands/AlignToNote.java b/src/main/java/org/carlmontrobotics/commands/AlignToNote.java index db5ba9f5..d40cde19 100644 --- a/src/main/java/org/carlmontrobotics/commands/AlignToNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AlignToNote.java @@ -18,5 +18,4 @@ public AlignToNote(Drivetrain dt) { return new RotateToFieldRelativeAngle(fieldOrientedTargetAngle, dt); }); } - //REMINDER TO UPLOAD SHOOTER LIMELIGHT WITH THE PIPELINE MODEL :D } From 8e0cee2ddbbb8ca109093e0f736af4d1776f01ce Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:45:03 -0700 Subject: [PATCH 05/20] swim shady constants --- .../java/org/carlmontrobotics/Constants.java | 254 +++++++++--------- 1 file changed, 132 insertions(+), 122 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index 43be980c..a614278d 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -25,128 +25,138 @@ public final class Constants { public static final double g = 9.81; //meters per second squared public static final class Drivetrainc { - - //#region Subsystem Constants - - public static final double wheelBase = Units.inchesToMeters(16.75); - public static final double trackWidth = Units.inchesToMeters(23.75); - // "swerveRadius" is the distance from the center of the robot to one of the modules - public static final double swerveRadius = Math.sqrt(Math.pow(wheelBase / 2, 2) + Math.pow(trackWidth / 2, 2)); - // The gearing reduction from the drive motor controller to the wheels - // Gearing for the Swerve Modules is 6.75 : 1 - public static final double driveGearing = 6.75; - - public static final double driveModifier = 1; - public static final double wheelDiameterMeters = Units.inchesToMeters(4.0) * 7.36/7.65 /* empirical correction */; - public static final double mu = 0.7; /* 70/83.2; */ - - public static final double NEOFreeSpeed = 5676 * (2 * Math.PI) / 60; // radians/s - // Angular speed to translational speed --> v = omega * r / gearing - public static final double maxSpeed = NEOFreeSpeed * (wheelDiameterMeters / 2.0) / driveGearing; - public static final double maxForward = maxSpeed; //todo: use smart dashboard to figure this out - public static final double maxStrafe = maxSpeed; // todo: use smart dashboard to figure this out - // seconds it takes to go from 0 to 12 volts(aka MAX) - public static final double secsPer12Volts = 0.1; - - - - - // maxRCW is the angular velocity of the robot. - // Calculated by looking at one of the motors and treating it as a point mass moving around in a circle. - // Tangential speed of this point mass is maxSpeed and the radius of the circle is sqrt((wheelBase/2)^2 + (trackWidth/2)^2) - // Angular velocity = Tangential speed / radius - public static final double maxRCW = maxSpeed / swerveRadius; - - public static final boolean[] reversed = {false, false, false, false}; - // public static final boolean[] reversed = {true, true, true, true}; - // Determine correct turnZero constants (FL, FR, BL, BR) - public static final double[] turnZero = RobotBase.isSimulation() ? - new double[] {0, 0, 0, 0} : - new double[] {0, 0 , 0, 0};/*real values here*/ - - // kP, kI, and kD constants for turn motor controllers in the order of front-left, front-right, back-left, back-right. - // Determine correct turn PID constants - public static final double[] turnkP = {0.00374, 0.00374, 0.00374, 0.00374}; - public static final double[] turnkI = {0, 0, 0, 0}; - public static final double[] turnkD = {0, 0, 0, 0}; // todo: use d - public static final double[] turnkS = {0.2, 0.2, 0.2, 0.2}; - // V = kS + kV * v + kA * a - // 12 = 0.2 + 0.00463 * v - // v = (12 - 0.2) / 0.00463 = 2548.596 degrees/s - public static final double[] turnkV = {0.00463, 0.00463, 0.00463, 0.00463}; - public static final double[] turnkA = {0.000115, 0.000115, 0.000115, 0.000115}; - - // kP is an average of the forward and backward kP values - // Forward: 1.72, 1.71, 1.92, 1.94 - // Backward: 1.92, 1.92, 2.11, 1.89 - public static final double[] drivekP = {1.82, 1.815, 2.015, 1.915}; - public static final double[] drivekI = {0, 0, 0, 0}; - public static final double[] drivekD = {0, 0, 0, 0}; - public static final boolean[] driveInversion = {false, false, false, false}; - public static final boolean[] turnInversion = {true, true, true, true}; - - public static final double[] kForwardVolts = {0.129, 0.108, 0.14, 0.125}; - public static final double[] kBackwardVolts = {0.115, 0.169, 0.13, 0.148}; - - public static final double[] kForwardVels = {2.910/1.1, 2.970/1.1, 2.890/1.1, 2.930/1.1}; - public static final double[] kBackwardVels = {2.890/1.1, 2.800/1.1, 2.850/1.1, 2.820/1.1}; - public static final double[] kForwardAccels = {0.145, 0.149, 0.192, 0.198}; - public static final double[] kBackwardAccels = {0.192, 0.187, 0.264, 0.176}; - - public static final double autoMaxSpeedMps = 0.35 * 4.4; // Meters / second - public static final double autoMaxAccelMps2 = mu * g; // Meters / seconds^2 - public static final double autoMaxVolt = 10.0; // For Drivetrain voltage constraint in RobotPath.java - // The maximum acceleration the robot can achieve is equal to the coefficient of static friction times the gravitational acceleration - // a = mu * 9.8 m/s^2 - public static final double autoCentripetalAccel = mu * g * 2; - - public static final boolean isGyroReversed = true; - - // PID values are listed in the order kP, kI, and kD - public static final double[] xPIDController = {4, 0.0, 0.0}; - public static final double[] yPIDController = {4, 0.0, 0.0}; - public static final double[] thetaPIDController = {0.10, 0.0, 0.001}; - - public static final SwerveConfig swerveConfig = new SwerveConfig(wheelDiameterMeters, driveGearing, mu, autoCentripetalAccel, kForwardVolts, kForwardVels, kForwardAccels, kBackwardVolts, kBackwardVels, kBackwardAccels, drivekP, drivekI, drivekD, turnkP, turnkI, turnkD, turnkS, turnkV, turnkA, turnZero, driveInversion, reversed, driveModifier, turnInversion); - - public static final Transform limelightTransformForPoseEstimation = Transform.BOTPOSE_WPIBLUE; - - //#endregion - - //#region Ports - - public static final int driveFrontLeftPort = 11; - public static final int driveFrontRightPort = 16; - public static final int driveBackLeftPort = 1; - public static final int driveBackRightPort = 18; - - public static final int turnFrontLeftPort = 12; - public static final int turnFrontRightPort = 14; - public static final int turnBackLeftPort = 20; - public static final int turnBackRightPort = 19; - - public static final int canCoderPortFL = 1; - public static final int canCoderPortFR = 2; - public static final int canCoderPortBL = 3; - public static final int canCoderPortBR = 4; - - //#endregion - - //#region Command Constants - - public static final double kNormalDriveSpeed = 1; // Percent Multiplier - public static final double kNormalDriveRotation = 0.5; // Percent Multiplier - public static final double kSlowDriveSpeed = 0.4; // Percent Multiplier - public static final double kSlowDriveRotation = 0.250; // Percent Multiplier - public static final double kAlignMultiplier = 1D/3D; - public static final double kAlignForward = 0.6; - - public static final double wheelTurnDriveSpeed = 0.0001; // Meters / Second ; A non-zero speed just used to orient the wheels to the correct angle. This should be very small to avoid actually moving the robot. - - public static final double[] positionTolerance = {Units.inchesToMeters(.5), Units.inchesToMeters(.5), 5}; // Meters, Meters, Degrees - public static final double[] velocityTolerance = {Units.inchesToMeters(1), Units.inchesToMeters(1), 5}; // Meters, Meters, Degrees/Second - - //#endregion + //#region Subsystem Constants + + public static final double wheelBase = Units.inchesToMeters(19.75); + public static final double trackWidth = Units.inchesToMeters(28.75); + // "swerveRadius" is the distance from the center of the robot to one of the modules + public static final double swerveRadius = Math.sqrt(Math.pow(wheelBase / 2, 2) + Math.pow(trackWidth / 2, 2)); + // The gearing reduction from the drive motor controller to the wheels + // Gearing for the Swerve Modules is 6.75 : 1 + public static final double driveGearing = 6.75; + // Turn motor shaft to "module shaft" + public static final double turnGearing = 150 / 7; + + public static final double driveModifier = 1; + public static final double wheelDiameterMeters = Units.inchesToMeters(4.0) * 7.36/7.65 /* empirical correction */; + public static final double mu = 1; /* 70/83.2; */ + + public static final double NEOFreeSpeed = 5676 * (2 * Math.PI) / 60; // radians/s + // Angular speed to translational speed --> v = omega * r / gearing + public static final double maxSpeed = NEOFreeSpeed * (wheelDiameterMeters / 2.0) / driveGearing; + public static final double maxForward = maxSpeed; //todo: use smart dashboard to figure this out + public static final double maxStrafe = maxSpeed; // todo: use smart dashboard to figure this out + // seconds it takes to go from 0 to 12 volts(aka MAX) + public static final double secsPer12Volts = 0.1; + + // maxRCW is the angular velocity of the robot. + // Calculated by looking at one of the motors and treating it as a point mass moving around in a circle. + // Tangential speed of this point mass is maxSpeed and the radius of the circle is sqrt((wheelBase/2)^2 + (trackWidth/2)^2) + // Angular velocity = Tangential speed / radius + public static final double maxRCW = maxSpeed / swerveRadius; + + public static final boolean[] reversed = {false, false, false, false}; + // public static final boolean[] reversed = {true, true, true, true}; + // Determine correct turnZero constants (FL, FR, BL, BR) + public static final double[] turnZeroDeg = RobotBase.isSimulation() ? + new double[] {0, 0, 0, 0} : + new double[] {85.7812, 85.0782 , -96.9433, -162.9492};/*real values here*/ + + // kP, kI, and kD constants for turn motor controllers in the order of front-left, front-right, back-left, back-right. + // Determine correct turn PID constants + public static final double[] turnkP = {51.078,60.885,60.946,60.986}; //{0.00374, 0.00374, 0.00374, 0.00374}; + public static final double[] turnkI = {0, 0, 0, 0}; + public static final double[] turnkD = {0/*dont edit */, 0.5, 0.42, 1}; // todo: use d + //public static final double[] turnkS = {0.2, 0.2, 0.2, 0.2}; + public static final double[] turnkS = {0.13027, 0.17026, 0.2, 0.23262}; + + // V = kS + kV * v + kA * a + // 12 = 0.2 + 0.00463 * v + // v = (12 - 0.2) / 0.00463 = 2548.596 degrees/s + public static final double[] turnkV = {2.6532, 2.7597, 2.7445, 2.7698}; + public static final double[] turnkA = {0.17924, 0.17924, 0.17924, 0.17924}; + + // kP is an average of the forward and backward kP values + // Forward: 1.72, 1.71, 1.92, 1.94 + // Backward: 1.92, 1.92, 2.11, 1.89 + // Order of modules: (FL, FR, BL, BR) + public static final double[] drivekP = {2.8, 2.8, 2.8, 2.8}; //{1.82/100, 1.815/100, 2.015/100, 1.915/100}; + public static final double[] drivekI = {0, 0, 0, 0}; + public static final double[] drivekD = {0, 0, 0, 0}; + public static final boolean[] driveInversion = {false, false, false, false}; + public static final boolean[] turnInversion = {true, true, true, true}; + + public static final double[] kForwardVolts = {0.26744, 0.31897, 0.27967, 0.2461}; + public static final double[] kBackwardVolts = kForwardVolts; + + public static final double[] kForwardVels = {2.81, 2.9098, 2.8378, 2.7391}; + public static final double[] kBackwardVels = kForwardVels; + public static final double[] kForwardAccels = {1.1047/2, 0.79422/2, 0.77114/2, 1.1003/2}; + public static final double[] kBackwardAccels = kForwardAccels; + + public static final double autoMaxSpeedMps = 0.35 * 4.4; // Meters / second + public static final double autoMaxAccelMps2 = mu * g; // Meters / seconds^2 + public static final double autoMaxVolt = 10.0; // For Drivetrain voltage constraint in RobotPath.java + // The maximum acceleration the robot can achieve is equal to the coefficient of static friction times the gravitational acceleration + // a = mu * 9.8 m/s^2 + public static final double autoCentripetalAccel = mu * g * 2; + + public static final boolean isGyroReversed = true; + + // PID values are listed in the order kP, kI, and kD + public static final double[] xPIDController = {4, 0.0, 0.0}; + public static final double[] yPIDController = {4, 0.0, 0.0}; + public static final double[] thetaPIDController = {0.10, 0.0, 0.001}; + + public static final SwerveConfig swerveConfig = new SwerveConfig(wheelDiameterMeters, driveGearing, mu, autoCentripetalAccel, kForwardVolts, kForwardVels, kForwardAccels, kBackwardVolts, kBackwardVels, kBackwardAccels, drivekP, drivekI, drivekD, turnkP, turnkI, turnkD, turnkS, turnkV, turnkA, turnZeroDeg, driveInversion, reversed, driveModifier, turnInversion); + + //public static final Limelight.Transform limelightTransformForPoseEstimation = Transform.BOTPOSE_WPIBLUE; + + //#endregion + + //#region Ports + + public static final int driveFrontLeftPort = 8; //correct + public static final int driveFrontRightPort = 13; // correct + public static final int driveBackLeftPort = 5; //correct + public static final int driveBackRightPort = 11; //correct + + public static final int turnFrontLeftPort = 7; //cprrect + public static final int turnFrontRightPort = 14; //correct + public static final int turnBackLeftPort = 6; //correct + public static final int turnBackRightPort = 12; //correct + + public static final int canCoderPortFL = 4; + public static final int canCoderPortFR = 2; + public static final int canCoderPortBL = 3; + public static final int canCoderPortBR = 1; + + //#endregion + + //#region Command Constants + + public static double kNormalDriveSpeed = 1; // Percent Multiplier + public static double kNormalDriveRotation = 0.5; // Percent Multiplier + public static double kSlowDriveSpeed = 0.4; // Percent Multiplier + public static double kSlowDriveRotation = 0.250; // Percent Multiplier + public static double kAlignMultiplier = 1D/3D; + public static final double kAlignForward = 0.6; + + public static final double wheelTurnDriveSpeed = 0.0001; // Meters / Second ; A non-zero speed just used to orient the wheels to the correct angle. This should be very small to avoid actually moving the robot. + + public static final double[] positionTolerance = {Units.inchesToMeters(.5), Units.inchesToMeters(.5), 5}; // Meters, Meters, Degrees + public static final double[] velocityTolerance = {Units.inchesToMeters(1), Units.inchesToMeters(1), 5}; // Meters, Meters, Degrees/Second + + //#endregion + + //#endregion + //#region Subsystem Constants + + // "swerveRadius" is the distance from the center of the robot to one of the modules + public static final double turnkP_avg = (turnkP[0]+turnkP[1]+turnkP[2]+turnkP[3])/4; + public static final double turnIzone = .1; + + public static final double driveIzone = .1; } public static final class Armc { From 41915d855a9e3e98a2941ce6abdad665109623fe Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:11:45 -0700 Subject: [PATCH 06/20] its 11:11 --- src/main/java/org/carlmontrobotics/Constants.java | 4 ++-- src/main/java/org/carlmontrobotics/RobotContainer.java | 6 +++--- .../carlmontrobotics/commands/AutoMATICALLYGetNote.java | 4 ++-- .../java/org/carlmontrobotics/subsystems/Limelight.java | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index 43be980c..7467679a 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -158,9 +158,9 @@ public static final class Limelightc { public static final String INTAKE_LL_NAME = "limelight-intake"; public static final String SHOOTER_LL_NAME = "limelight-shooter"; - public static final double ERROR_TOLERANCE = 0.1; + public static final double ERROR_TOLERANCE_RAD = 0.1; public static final double HORIZONTAL_FOV_DEG = 0; - public static final double RESOLUTION_WIDTH = 640; + public static final double RESOLUTION_WIDTH_PIX = 640; public static final double MOUNT_ANGLE_DEG_SHOOTER = 25; //23.228 public static final double MOUNT_ANGLE_DEG_INTAKE = 17.5 + 0; //23.228 public static final double HEIGHT_FROM_GROUND_METERS_SHOOTER = Units.inchesToMeters(56); //16.6 diff --git a/src/main/java/org/carlmontrobotics/RobotContainer.java b/src/main/java/org/carlmontrobotics/RobotContainer.java index eb5c28a9..46ecaa2b 100644 --- a/src/main/java/org/carlmontrobotics/RobotContainer.java +++ b/src/main/java/org/carlmontrobotics/RobotContainer.java @@ -76,9 +76,9 @@ private void setDefaultCommands() { )); } private void setBindingsDriver() { - new JoystickButton(driverController, 1).onTrue(new AlignToApriltag(drivetrain)); //button A - new JoystickButton(driverController, 2).onTrue(new AlignToNote(drivetrain)); //button b? - new JoystickButton(driverController, 2).whileTrue(new AlignToNote(drivetrain)); //button x? + new JoystickButton(driverController, 1).whileTrue(new AlignToApriltag(drivetrain)); //button A + new JoystickButton(driverController, 2).whileTrue(new AlignToNote(drivetrain)); //button b? + new JoystickButton(driverController, 3).whileTrue(new AutoMATICALLYGetNote(drivetrain)); //button x? // reset field orientation?? // new JoystickButton(driverController, Driver.resetFieldOrientationButton).onTrue( // new InstantCommand(drivetrain::resetFieldOrientation)); diff --git a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java index ad4e6a7e..f88f7f5e 100644 --- a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java @@ -23,9 +23,9 @@ public class AutoMATICALLYGetNote extends Command { private IntakeShooter effector; private Limelight limelight; - public AutoMATICALLYGetNote(Drivetrain dt, IntakeShooter effector) { + public AutoMATICALLYGetNote(Drivetrain dt /*IntakeShooter effector*/) { addRequirements(this.dt = dt); - addRequirements(this.effector = effector); + //addRequirements(this.effector = effector); // Use addRequirements() here to declare subsystem dependencies. } diff --git a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java index 95cda1ca..b1b12b93 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java @@ -54,10 +54,10 @@ public void updateBotPose3d(){ public Pose2d getCurrentPose(){ Pose2d estimatedPos = poseEstimator.getEstimatedPosition(); - System.out.println(estimatedPos.getX()); - System.out.println(estimatedPos.getY()); - System.out.println(estimatedPos.getRotation().getDegrees() + "degrees"); - return poseEstimator.getEstimatedPosition(); + SmartDashboard.putNumber("estimated x", estimatedPos.getX()); + SmartDashboard.putNumber("estimated y", estimatedPos.getY()); + SmartDashboard.putNumber("estimated rotation (deg)", estimatedPos.getRotation().getDegrees()); + return estimatedPos; } From 5ed620ff93ab741fa7c19e7e020a6c1274eabf5c Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:37:37 -0700 Subject: [PATCH 07/20] constants --- src/main/java/org/carlmontrobotics/Constants.java | 2 ++ .../commands/AutoMATICALLYGetNote.java | 13 ++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index 7467679a..056d8084 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -167,6 +167,8 @@ public static final class Limelightc { public static final double HEIGHT_FROM_GROUND_METERS_INTAKE = Units.inchesToMeters(56); //16.6 public static final double ARM_TO_OUTTAKE_OFFSET_DEG= 115; public static final double NOTE_HEIGHT = Units.inchesToMeters(2); + public static final double xyPControl = 2; + public static final double thetaPControl = 2; public static final class Apriltag { public static final int RED_SPEAKER_CENTER_TAG_ID = 4; public static final int BLUE_SPEAKER_CENTER_TAG_ID = 7; diff --git a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java index f88f7f5e..eb71f206 100644 --- a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java @@ -4,6 +4,9 @@ package org.carlmontrobotics.commands; +import static org.carlmontrobotics.Constants.Limelightc.thetaPControl; +import static org.carlmontrobotics.Constants.Limelightc.xyPControl; + import org.carlmontrobotics.Constants.*; import org.carlmontrobotics.subsystems.*; @@ -37,11 +40,11 @@ public void initialize() { @Override public void execute() { - double radErr = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); - double distErr = limelight.getDistanceToNote(); //meters - double forwardErr = distErr * Math.cos(radErr); - double strafeErr = distErr * Math.sin(radErr); - dt.drive(Math.max(forwardErr*2, .5), Math.max(strafeErr*2, .5), Math.max(radErr*2,.5)); + double angleErrRad = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); + double distErrMeters = limelight.getDistanceToNote(); //meters + double forwardErrMeters = distErrMeters * Math.cos(angleErrRad); + double strafeErrMeters = distErrMeters * Math.sin(angleErrRad); + dt.drive(Math.max(forwardErrMeters*xyPControl, .5), Math.max(strafeErrMeters*xyPControl, .5), Math.max(angleErrRad*thetaPControl,.5)); //180deg is about 6.2 rad/sec, min is .5rad/sec } From c9ca70fc1a46d5a737beaf8e1940d2cc061a24d5 Mon Sep 17 00:00:00 2001 From: DriverStationComputer Date: Sun, 24 Mar 2024 15:45:00 -0700 Subject: [PATCH 08/20] worksession --- build.gradle | 2 +- .../java/org/carlmontrobotics/Constants.java | 8 +-- .../org/carlmontrobotics/RobotContainer.java | 8 +-- .../commands/AlignToNote.java | 57 ++++++++++++++--- .../commands/AutoMATICALLYGetNote.java | 21 +++++-- .../carlmontrobotics/commands/MoveToNote.java | 61 +++++++++++++++++++ .../subsystems/Limelight.java | 9 +-- 7 files changed, 137 insertions(+), 29 deletions(-) create mode 100644 src/main/java/org/carlmontrobotics/commands/MoveToNote.java diff --git a/build.gradle b/build.gradle index 8a52caac..6c895a0d 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ dependencies { simulationRelease wpi.sim.enableRelease() testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' - implementation "com.github.deepbluerobotics:lib199:2024-SNAPSHOT" + implementation "com.github.deepbluerobotics:lib199:cc93080eab462da161d0d47eda253ac8b31495ee" } test { diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index a614278d..b9b34f70 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -106,7 +106,7 @@ public static final class Drivetrainc { // PID values are listed in the order kP, kI, and kD public static final double[] xPIDController = {4, 0.0, 0.0}; public static final double[] yPIDController = {4, 0.0, 0.0}; - public static final double[] thetaPIDController = {0.10, 0.0, 0.001}; + public static final double[] thetaPIDController = {0.05, 0.0, 0.00}; public static final SwerveConfig swerveConfig = new SwerveConfig(wheelDiameterMeters, driveGearing, mu, autoCentripetalAccel, kForwardVolts, kForwardVels, kForwardAccels, kBackwardVolts, kBackwardVels, kBackwardAccels, drivekP, drivekI, drivekD, turnkP, turnkI, turnkD, turnkS, turnkV, turnkA, turnZeroDeg, driveInversion, reversed, driveModifier, turnInversion); @@ -172,11 +172,11 @@ public static final class Limelightc { public static final double HORIZONTAL_FOV_DEG = 0; public static final double RESOLUTION_WIDTH = 640; public static final double MOUNT_ANGLE_DEG_SHOOTER = 25; //23.228 - public static final double MOUNT_ANGLE_DEG_INTAKE = 17.5 + 0; //23.228 + public static final double MOUNT_ANGLE_DEG_INTAKE = 22; //23.228 public static final double HEIGHT_FROM_GROUND_METERS_SHOOTER = Units.inchesToMeters(56); //16.6 - public static final double HEIGHT_FROM_GROUND_METERS_INTAKE = Units.inchesToMeters(56); //16.6 + public static final double HEIGHT_FROM_GROUND_METERS_INTAKE = Units.inchesToMeters(52); //16.6 public static final double ARM_TO_OUTTAKE_OFFSET_DEG= 115; - public static final double NOTE_HEIGHT = Units.inchesToMeters(2); + public static final double NOTE_HEIGHT = Units.inchesToMeters(0); public static final class Apriltag { public static final int RED_SPEAKER_CENTER_TAG_ID = 4; public static final int BLUE_SPEAKER_CENTER_TAG_ID = 7; diff --git a/src/main/java/org/carlmontrobotics/RobotContainer.java b/src/main/java/org/carlmontrobotics/RobotContainer.java index eb5c28a9..b70fb5ba 100644 --- a/src/main/java/org/carlmontrobotics/RobotContainer.java +++ b/src/main/java/org/carlmontrobotics/RobotContainer.java @@ -17,7 +17,7 @@ import edu.wpi.first.wpilibj.DigitalInput; import edu.wpi.first.wpilibj.GenericHID; import edu.wpi.first.wpilibj.XboxController.Axis; - +import edu.wpi.first.wpilibj.XboxController.Button; //commands import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.Commands; @@ -76,9 +76,9 @@ private void setDefaultCommands() { )); } private void setBindingsDriver() { - new JoystickButton(driverController, 1).onTrue(new AlignToApriltag(drivetrain)); //button A - new JoystickButton(driverController, 2).onTrue(new AlignToNote(drivetrain)); //button b? - new JoystickButton(driverController, 2).whileTrue(new AlignToNote(drivetrain)); //button x? + new JoystickButton(driverController, Button.kB.value).onTrue(new AutoMATICALLYGetNote(drivetrain, limelight)); //button b + //new JoystickButton(driverController, 2).onTrue(new AlignToNote(drivetrain)); //button b? + new JoystickButton(driverController, Button.kA.value).whileTrue(new AlignToNote(drivetrain)); //button x? // reset field orientation?? // new JoystickButton(driverController, Driver.resetFieldOrientationButton).onTrue( // new InstantCommand(drivetrain::resetFieldOrientation)); diff --git a/src/main/java/org/carlmontrobotics/commands/AlignToNote.java b/src/main/java/org/carlmontrobotics/commands/AlignToNote.java index d40cde19..c8296df7 100644 --- a/src/main/java/org/carlmontrobotics/commands/AlignToNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AlignToNote.java @@ -4,18 +4,55 @@ package org.carlmontrobotics.commands; -import static org.carlmontrobotics.Constants.Limelightc.*; import org.carlmontrobotics.subsystems.Drivetrain; -import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.wpilibj2.command.ProxyCommand; import org.carlmontrobotics.subsystems.LimelightHelpers; -public class AlignToNote extends ProxyCommand { +import edu.wpi.first.math.MathUtil; +import edu.wpi.first.math.controller.PIDController; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.util.sendable.SendableRegistry; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.Command; +import static org.carlmontrobotics.Constants.Drivetrainc.*; +import static org.carlmontrobotics.Constants.Limelightc.INTAKE_LL_NAME; + +public class AlignToNote extends Command { + + public final TeleopDrive teleopDrive; + public final Drivetrain drivetrain; + + public final PIDController rotationPID = new PIDController(thetaPIDController[0], thetaPIDController[1], thetaPIDController[2]); + + public AlignToNote(Drivetrain drivetrain) { + this.drivetrain = drivetrain; + this.teleopDrive = (TeleopDrive) drivetrain.getDefaultCommand(); + + rotationPID.enableContinuousInput(-180, 180); + Rotation2d targetAngle = Rotation2d.fromDegrees(drivetrain.getHeading()).minus(Rotation2d.fromDegrees(LimelightHelpers.getTX(INTAKE_LL_NAME))); + rotationPID.setSetpoint(MathUtil.inputModulus(targetAngle.getDegrees(), -180, 180)); + rotationPID.setTolerance(positionTolerance[2], velocityTolerance[2]); + SendableRegistry.addChild(this, rotationPID); + //SmartDashboard.pu + + addRequirements(drivetrain); + } + + @Override + public void execute() { + Rotation2d targetAngle = Rotation2d.fromDegrees(drivetrain.getHeading()).minus(Rotation2d.fromDegrees(LimelightHelpers.getTX(INTAKE_LL_NAME))); + rotationPID.setSetpoint(MathUtil.inputModulus(targetAngle.getDegrees(), -180, 180)); + if (teleopDrive == null) drivetrain.drive(0, 0, rotationPID.calculate(drivetrain.getHeading())); + else { + double[] driverRequestedSpeeds = teleopDrive.getRequestedSpeeds(); + drivetrain.drive(driverRequestedSpeeds[0], driverRequestedSpeeds[1], rotationPID.calculate(drivetrain.getHeading())); + } + } - public AlignToNote(Drivetrain dt) { - super(() -> { - Rotation2d fieldOrientedTargetAngle = Rotation2d.fromDegrees(LimelightHelpers.getTX(INTAKE_LL_NAME)).plus(Rotation2d.fromDegrees(dt.getHeading())); - return new RotateToFieldRelativeAngle(fieldOrientedTargetAngle, dt); - }); - } + @Override + public boolean isFinished() { + return false; + // SmartDashboard.putBoolean("At Setpoint", rotationPID.atSetpoint()); + // SmartDashboard.putNumber("Error", rotationPID.getPositionError()); + // return rotationPID.atSetpoint(); + } } diff --git a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java index ad4e6a7e..e3fba1f2 100644 --- a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java @@ -9,6 +9,8 @@ import edu.wpi.first.math.geometry.Rotation2d; import edu.wpi.first.math.util.Units; +import edu.wpi.first.wpilibj.Timer; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.InstantCommand; import edu.wpi.first.wpilibj2.command.ParallelCommandGroup; @@ -20,27 +22,33 @@ public class AutoMATICALLYGetNote extends Command { /** Creates a new AutoMATICALLYGetNote. */ private Drivetrain dt; - private IntakeShooter effector; - private Limelight limelight; + //private IntakeShooter effector; + private Limelight ll; + private Timer timer = new Timer(); - public AutoMATICALLYGetNote(Drivetrain dt, IntakeShooter effector) { + public AutoMATICALLYGetNote(Drivetrain dt, Limelight ll /*IntakeShooter effector*/) { addRequirements(this.dt = dt); - addRequirements(this.effector = effector); + addRequirements(this.ll = ll); + //addRequirements(this.effector = effector); // Use addRequirements() here to declare subsystem dependencies. } @Override public void initialize() { + timer.reset(); + timer.start(); //new Intake().finallyDo(()->{this.end(false);}); + SmartDashboard.putBoolean("end", false); dt.setFieldOriented(false); } @Override public void execute() { double radErr = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); - double distErr = limelight.getDistanceToNote(); //meters + double distErr = ll.getDistanceToNote(); //meters double forwardErr = distErr * Math.cos(radErr); double strafeErr = distErr * Math.sin(radErr); + // dt.drive(0,0,0); dt.drive(Math.max(forwardErr*2, .5), Math.max(strafeErr*2, .5), Math.max(radErr*2,.5)); //180deg is about 6.2 rad/sec, min is .5rad/sec } @@ -49,11 +57,12 @@ public void execute() { @Override public void end(boolean interrupted) { dt.setFieldOriented(true); + SmartDashboard.putBoolean("end", true); } // Returns true when the command should end. @Override public boolean isFinished() { - return false; + return timer.get() >= 0.5; } } diff --git a/src/main/java/org/carlmontrobotics/commands/MoveToNote.java b/src/main/java/org/carlmontrobotics/commands/MoveToNote.java new file mode 100644 index 00000000..67a6abb3 --- /dev/null +++ b/src/main/java/org/carlmontrobotics/commands/MoveToNote.java @@ -0,0 +1,61 @@ +// 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 org.carlmontrobotics.commands; + +import org.carlmontrobotics.Constants.Limelightc; +import org.carlmontrobotics.subsystems.Drivetrain; +import org.carlmontrobotics.subsystems.Limelight; +import org.carlmontrobotics.subsystems.LimelightHelpers; + +import edu.wpi.first.math.util.Units; +import edu.wpi.first.wpilibj.Timer; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.Command; + +public class MoveToNote extends Command { + private final Drivetrain dt; + private final Limelight ll; + private Timer timer = new Timer(); + /** Creates a new MoveToNote. */ + public MoveToNote(Drivetrain dt, Limelight ll) { + // Use addRequirements() here to declare subsystem dependencies. + addRequirements(this.dt=dt); + addRequirements(this.ll=ll); + } + + // Called when the command is initially scheduled. + @Override + public void initialize() { + new AlignToNote(dt); + timer.reset(); + timer.start(); + //new Intake().finallyDo(()->{this.end(false);}); + SmartDashboard.putBoolean("end", false); + dt.setFieldOriented(false); + } + + // Called every time the scheduler runs while the command is scheduled. + @Override + public void execute() { + double radErr = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); + double distErr = ll.getDistanceToNote(); //meters + double forwardErr = distErr * Math.cos(radErr); + // dt.drive(0,0,0); + dt.drive(Math.max(forwardErr*2, .5), 0, 0); + //180deg is about 6.2 rad/sec, min is .5rad/sec + } + + // Called once the command ends or is interrupted. + @Override + public void end(boolean interrupted) { + dt.setFieldOriented(true); + } + + // Returns true when the command should end. + @Override + public boolean isFinished() { + return timer.get() >= 0.5; + } +} diff --git a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java index 95cda1ca..98c2dc97 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java @@ -45,6 +45,7 @@ public void periodic() { updateBotPose3d(); getDistanceToTargetSpeaker(); getCurrentPose(); + getDistanceToNote(); } public void updateBotPose3d(){ @@ -65,20 +66,20 @@ public double getDistanceToTargetSpeaker(){ if (LimelightHelpers.getFiducialID(SHOOTER_LL_NAME) == RED_SPEAKER_CENTER_TAG_ID || LimelightHelpers.getFiducialID(SHOOTER_LL_NAME) == BLUE_SPEAKER_CENTER_TAG_ID){ Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG_SHOOTER).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(SHOOTER_LL_NAME))); double distance = (SPEAKER_CENTER_HEIGHT_METERS - HEIGHT_FROM_GROUND_METERS_SHOOTER) / angleToGoal.getTan(); - SmartDashboard.putNumber("limelight distance", distance); + //SmartDashboard.putNumber("limelight distance", distance); return distance; } else{ - SmartDashboard.putNumber("limelight distance", -1); + //SmartDashboard.putNumber("limelight distance", -1); return -1; } } public double getDistanceToNote(){ Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG_INTAKE).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(INTAKE_LL_NAME))); - double distance = (NOTE_HEIGHT - HEIGHT_FROM_GROUND_METERS_INTAKE) / angleToGoal.getTan(); - SmartDashboard.putNumber("limelight distance to note", distance); + double distance = -(NOTE_HEIGHT - HEIGHT_FROM_GROUND_METERS_INTAKE) / angleToGoal.getTan(); + SmartDashboard.putNumber("limelight distance", distance); return distance; } From 1a1a13d7ed82d7d3cb277941648dbe251af22841 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:01:27 -0700 Subject: [PATCH 09/20] my math for driving was wrong + less magic numbers (i will unmagic the last numbers after they get turned) --- src/main/java/org/carlmontrobotics/Constants.java | 2 ++ .../commands/AutoMATICALLYGetNote.java | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index b9b34f70..e696c788 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -177,6 +177,8 @@ public static final class Limelightc { public static final double HEIGHT_FROM_GROUND_METERS_INTAKE = Units.inchesToMeters(52); //16.6 public static final double ARM_TO_OUTTAKE_OFFSET_DEG= 115; public static final double NOTE_HEIGHT = Units.inchesToMeters(0); + public static final double MIN_MOVEMENT_METERSPSEC = 0.5; + public static final double MIN_MOVEMENT_RADSPSEC = 0.5; public static final class Apriltag { public static final int RED_SPEAKER_CENTER_TAG_ID = 4; public static final int BLUE_SPEAKER_CENTER_TAG_ID = 7; diff --git a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java index e3fba1f2..1d926558 100644 --- a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java @@ -4,6 +4,9 @@ package org.carlmontrobotics.commands; +import static org.carlmontrobotics.Constants.Limelightc.MIN_MOVEMENT_METERSPSEC; +import static org.carlmontrobotics.Constants.Limelightc.MIN_MOVEMENT_RADSPSEC; + import org.carlmontrobotics.Constants.*; import org.carlmontrobotics.subsystems.*; @@ -44,12 +47,11 @@ public void initialize() { @Override public void execute() { - double radErr = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); - double distErr = ll.getDistanceToNote(); //meters - double forwardErr = distErr * Math.cos(radErr); - double strafeErr = distErr * Math.sin(radErr); + double angleErrRad = Units.degreesToRadians(LimelightHelpers.getTX(Limelightc.INTAKE_LL_NAME)); + double forwardDistErrMeters = ll.getDistanceToNote(); + double strafeDistErrMeters = forwardDistErrMeters * Math.tan(angleErrRad); // dt.drive(0,0,0); - dt.drive(Math.max(forwardErr*2, .5), Math.max(strafeErr*2, .5), Math.max(radErr*2,.5)); + dt.drive(Math.max(forwardDistErrMeters*2, MIN_MOVEMENT_METERSPSEC), Math.max(strafeDistErrMeters*2, MIN_MOVEMENT_METERSPSEC), Math.max(angleErrRad*2,MIN_MOVEMENT_RADSPSEC)); //180deg is about 6.2 rad/sec, min is .5rad/sec } From ed260dedf090ab0f76dd5e6154d46845d40fb03a Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:37:45 -0700 Subject: [PATCH 10/20] removed reqs --- src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java b/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java index c54475c3..18fccd27 100644 --- a/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java +++ b/src/main/java/org/carlmontrobotics/commands/AlignToApriltag.java @@ -17,6 +17,5 @@ public AlignToApriltag(Drivetrain dt) { Rotation2d fieldOrientedTargetAngle = Rotation2d.fromDegrees(LimelightHelpers.getTX(SHOOTER_LL_NAME)).plus(Rotation2d.fromDegrees(dt.getHeading())); return new RotateToFieldRelativeAngle(fieldOrientedTargetAngle, dt); }); - addRequirements(dt); } } \ No newline at end of file From e31a260eace7b301d7d34aebc7013f8ebdeec964 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Tue, 26 Mar 2024 00:11:35 -0700 Subject: [PATCH 11/20] math fix --- src/main/java/org/carlmontrobotics/Constants.java | 2 +- .../java/org/carlmontrobotics/subsystems/Limelight.java | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index e696c788..5fa46865 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -172,7 +172,7 @@ public static final class Limelightc { public static final double HORIZONTAL_FOV_DEG = 0; public static final double RESOLUTION_WIDTH = 640; public static final double MOUNT_ANGLE_DEG_SHOOTER = 25; //23.228 - public static final double MOUNT_ANGLE_DEG_INTAKE = 22; //23.228 + public static final double MOUNT_ANGLE_DEG_INTAKE = -22; //23.228 public static final double HEIGHT_FROM_GROUND_METERS_SHOOTER = Units.inchesToMeters(56); //16.6 public static final double HEIGHT_FROM_GROUND_METERS_INTAKE = Units.inchesToMeters(52); //16.6 public static final double ARM_TO_OUTTAKE_OFFSET_DEG= 115; diff --git a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java index 98c2dc97..1a605a68 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java @@ -3,12 +3,18 @@ import static org.carlmontrobotics.Constants.Limelightc.*; import static org.carlmontrobotics.Constants.Limelightc.Apriltag.*; +import java.util.List; + +import com.pathplanner.lib.path.GoalEndState; +import com.pathplanner.lib.path.PathConstraints; +import com.pathplanner.lib.path.PathPlannerPath; import edu.wpi.first.math.MathUtil; import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator; import edu.wpi.first.math.geometry.Pose2d; import edu.wpi.first.math.geometry.Pose3d; import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.geometry.Translation2d; import edu.wpi.first.math.util.Units; import edu.wpi.first.networktables.NetworkTable; import edu.wpi.first.networktables.NetworkTableEntry; @@ -78,7 +84,7 @@ public double getDistanceToTargetSpeaker(){ public double getDistanceToNote(){ Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG_INTAKE).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(INTAKE_LL_NAME))); - double distance = -(NOTE_HEIGHT - HEIGHT_FROM_GROUND_METERS_INTAKE) / angleToGoal.getTan(); + double distance = (HEIGHT_FROM_GROUND_METERS_INTAKE - NOTE_HEIGHT) / Math.tan(Math.abs(angleToGoal.getDegrees()));; SmartDashboard.putNumber("limelight distance", distance); return distance; } From 3c930bccc1923e02c620d8230f08a487eadcd7c9 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:32:35 -0700 Subject: [PATCH 12/20] (unfinished) creating a path to move to speaker from anywhere --- .../commands/MoveToSpeaker.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/main/java/org/carlmontrobotics/commands/MoveToSpeaker.java diff --git a/src/main/java/org/carlmontrobotics/commands/MoveToSpeaker.java b/src/main/java/org/carlmontrobotics/commands/MoveToSpeaker.java new file mode 100644 index 00000000..744de104 --- /dev/null +++ b/src/main/java/org/carlmontrobotics/commands/MoveToSpeaker.java @@ -0,0 +1,49 @@ +// 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 org.carlmontrobotics.commands; + +import static org.carlmontrobotics.Constants.Drivetrainc.*; + +import java.util.List; + +import org.carlmontrobotics.subsystems.Drivetrain; + +import com.pathplanner.lib.path.GoalEndState; +import com.pathplanner.lib.path.PathConstraints; +import com.pathplanner.lib.path.PathPlannerPath; +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.math.geometry.Translation2d; +import edu.wpi.first.wpilibj2.command.Command; + +public class MoveToSpeaker extends Command { + private final Drivetrain dt; + /** Creates a new MoveToSpeaker. */ + public MoveToSpeaker(Drivetrain dt) { + // Use addRequirements() here to declare subsystem dependencies. + addRequirements(this.dt = dt); + } + + // Called when the command is initially scheduled. + @Override + public void initialize() { + List bezierPoints = PathPlannerPath.bezierFromPoses(dt.getPose(), new Pose2d(1, 1, Rotation2d.fromDegrees(1))); + PathPlannerPath path = new PathPlannerPath(bezierPoints, new PathConstraints(autoMaxSpeedMps, autoMaxAccelMps2, maxRCW, 1), new GoalEndState(1, Rotation2d.fromDegrees(1))); + } + + // Called every time the scheduler runs while the command is scheduled. + @Override + public void execute() {} + + // Called once the command ends or is interrupted. + @Override + public void end(boolean interrupted) {} + + // Returns true when the command should end. + @Override + public boolean isFinished() { + return false; + } +} From fe944d2a17898e2049f574853479239234a319e2 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:32:49 -0700 Subject: [PATCH 13/20] angleToGoal can't be negative --- .../subsystems/Limelight.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java index 1a605a68..2c6d7b00 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Limelight.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Limelight.java @@ -3,22 +3,10 @@ import static org.carlmontrobotics.Constants.Limelightc.*; import static org.carlmontrobotics.Constants.Limelightc.Apriltag.*; -import java.util.List; - -import com.pathplanner.lib.path.GoalEndState; -import com.pathplanner.lib.path.PathConstraints; -import com.pathplanner.lib.path.PathPlannerPath; - -import edu.wpi.first.math.MathUtil; import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator; import edu.wpi.first.math.geometry.Pose2d; import edu.wpi.first.math.geometry.Pose3d; import edu.wpi.first.math.geometry.Rotation2d; -import edu.wpi.first.math.geometry.Translation2d; -import edu.wpi.first.math.util.Units; -import edu.wpi.first.networktables.NetworkTable; -import edu.wpi.first.networktables.NetworkTableEntry; -import edu.wpi.first.networktables.NetworkTableInstance; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.SubsystemBase; @@ -84,9 +72,15 @@ public double getDistanceToTargetSpeaker(){ public double getDistanceToNote(){ Rotation2d angleToGoal = Rotation2d.fromDegrees(MOUNT_ANGLE_DEG_INTAKE).plus(Rotation2d.fromDegrees(LimelightHelpers.getTY(INTAKE_LL_NAME))); - double distance = (HEIGHT_FROM_GROUND_METERS_INTAKE - NOTE_HEIGHT) / Math.tan(Math.abs(angleToGoal.getDegrees()));; - SmartDashboard.putNumber("limelight distance", distance); - return distance; + if (angleToGoal.getDegrees() <= 0) { + double distance = (HEIGHT_FROM_GROUND_METERS_INTAKE - NOTE_HEIGHT) / Math.tan(Math.abs(angleToGoal.getRadians()));; + SmartDashboard.putNumber("limelight distance", distance); + return distance; + } + else { + SmartDashboard.putNumber("limelight distance", -1); + return -1; + } } // public Pose3d getTargetPose() { From bf9c707cd82f36443a203d1b9ceecc91ec45c23b Mon Sep 17 00:00:00 2001 From: TuskAct2 <112046931+TuskAct2@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:50:48 +0000 Subject: [PATCH 14/20] Merge branch 'ledonbangbot-sofietheodore' into bangbot --- .../org/carlmontrobotics/subsystems/Led.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/org/carlmontrobotics/subsystems/Led.java diff --git a/src/main/java/org/carlmontrobotics/subsystems/Led.java b/src/main/java/org/carlmontrobotics/subsystems/Led.java new file mode 100644 index 00000000..3af50b82 --- /dev/null +++ b/src/main/java/org/carlmontrobotics/subsystems/Led.java @@ -0,0 +1,72 @@ +package org.carlmontrobotics.subsystems; + +import edu.wpi.first.wpilibj.AddressableLED; +import edu.wpi.first.wpilibj.AddressableLEDBuffer; +import edu.wpi.first.wpilibj.util.Color8Bit; +import edu.wpi.first.wpilibj2.command.SubsystemBase; + +import static org.carlmontrobotics.Constants.Led.*; +import org.carlmontrobotics.subsystems.IntakeShooter.*; + + +public class Led extends SubsystemBase{ + private final AddressableLEDBuffer ledBuffer = new AddressableLEDBuffer(100); + private final AddressableLED led = new AddressableLED(9); + private final IntakeShooter intakeshooter; + private int midpoint = (int)ledBuffer.getLength()/2; + //rounds down + // public static final double midpoint = Math.floor(ledLength/2); + //public static final int ledLength = led.getLength(); + + + public Led(IntakeShooter intakeShooter){ + this.intakeshooter = intakeShooter; + led.setLength(ledBuffer.getLength()); + led.setData(ledBuffer); + led.start(); + + setLedColor(DEFAULT_COLOR_BLUE, 0 , getLength()); + + } + public void setLedColor(Color8Bit color, int start, int end) { + for (int i = start; i < end ; i++) + ledBuffer.setRGB(i, color.red, color.green, color.blue); + led.setData(ledBuffer); + } + public int getLength(){ + return ledBuffer.getLength(); + } + @Override + public void periodic(){ + System.err.println("skdjfksd"); + if (intakeshooter.intakeDetectsNote() && !intakeshooter.outakeDetectsNote()) { + setLedColor(DETECT_NOTE_ORANGE, 0, midpoint); + //when intake TOF detects, but outtake TOF does not the bottom half of the LEDs become orange + + } + else if(!intakeshooter.intakeDetectsNote() && intakeshooter.outakeDetectsNote()){ + setLedColor(DETECT_NOTE_ORANGE,midpoint, getLength()); + //when outtake TOF detects, but intake TOF does not the top half of the LEDs become orange + } + else if (intakeshooter.intakeDetectsNote() && intakeshooter.outakeDetectsNote()) { + setLedColor(HOLDING_GREEN, 0, getLength()); + //when both TOFs detect and the end efforcter is holding the note the LEDS turn green + + } + else{ + setLedColor(DEFAULT_COLOR_BLUE, 0, getLength()); + //otherwise LEds are blue + } + + setLedColor(DEFAULT_COLOR_BLUE, 0, getLength()); + + + + + } + // nothing : setLedColor(defaultColr, 0, ledBuffer.getLength()) + //first tof detect: setLedColor(detectNote, 0, midpoint) + //second tof detec: setLedColor(detectNote, midpoint, ledBuffer.getLength()) + //both tof detect: setLedColor(holding, 0, ledBuffer.getLength()) + +} \ No newline at end of file From 7693ae3cbd640beb6f583cd94d3b077e8663f5b7 Mon Sep 17 00:00:00 2001 From: TuskAct2 <112046931+TuskAct2@users.noreply.github.com> Date: Tue, 26 Mar 2024 23:51:00 +0000 Subject: [PATCH 15/20] LED MERGE --- .../java/org/carlmontrobotics/Constants.java | 31 +-- .../org/carlmontrobotics/RobotContainer.java | 3 +- .../org/carlmontrobotics/commands/Intake.java | 14 +- .../carlmontrobotics/commands/MoveToPos.java | 1 - .../commands/PassToIntake.java | 1 - .../commands/PassToOutake.java | 2 +- .../carlmontrobotics/commands/RampToRPM.java | 2 +- .../org/carlmontrobotics/subsystems/Arm.java | 5 +- .../subsystems/AuxSystems.java | 222 ------------------ .../subsystems/Drivetrain.java | 4 +- 10 files changed, 30 insertions(+), 255 deletions(-) delete mode 100644 src/main/java/org/carlmontrobotics/subsystems/AuxSystems.java diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index 66c874c7..6e739e97 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -31,6 +31,7 @@ import edu.wpi.first.wpilibj.XboxController.Button; import edu.wpi.first.wpilibj2.command.button.POVButton; import edu.wpi.first.wpilibj.util.Color; +import org.carlmontrobotics.subsystems.Led; /** * The Constants class provides a convenient place for teams to hold robot-wide @@ -46,30 +47,17 @@ */ public final class Constants { public static final double g = 9.81; // meters per second squared - public static final class Led { - public static final int ledLength = 1000;//lower doesn't work but higher does - public static final int ledPort = 5; - - //public static final Color8Bit defaultColor = new Color8Bit(0, 0, 200); - - - - public static final Color8Bit detectNote = new Color8Bit(250,140,3); - public static final Color8Bit holding = new Color8Bit(0,250,0); - public static final Color8Bit ejectColor = new Color8Bit(250,250,0); - - public static final Color8Bit intakeColor = new Color8Bit(154,0,255); //intake detection = purple - public static final Color8Bit outtakeColor = new Color8Bit(0,9,255); //outtake detection = blue - public static final Color8Bit intakeouttakeColor = new Color8Bit(0,255,9); //intake and outtake (both) = green - //Red when nothing, purple/blue when intake/outtake detect only, green when both - - - //for weird alex stuf - public static Color8Bit startingColor = new Color8Bit(255,0,0); - + + + public static final Color8Bit DEFAULT_COLOR_BLUE = new Color8Bit(0, 0, 200); + public static final Color8Bit DETECT_NOTE_ORANGE = new Color8Bit(250,140,3); + public static final Color8Bit HOLDING_GREEN = new Color8Bit(0,250,0); + public static final int ledPort = 0; + //TODO: figure out how to get port of LED, it could be 0 or } + public static final class Effectorc { // PID values @@ -397,6 +385,7 @@ public static final class Manipulator { public static final int RAISE_CLIMBER = Button.kA.value; public static final int LOWER_CLIMBER = Button.kY.value; } + public static final double JOY_THRESH = 0.01; public static final double MIN_AXIS_TRIGGER_VALUE = 0.2;//woah, this is high. } diff --git a/src/main/java/org/carlmontrobotics/RobotContainer.java b/src/main/java/org/carlmontrobotics/RobotContainer.java index 988e0316..77621a0b 100644 --- a/src/main/java/org/carlmontrobotics/RobotContainer.java +++ b/src/main/java/org/carlmontrobotics/RobotContainer.java @@ -64,6 +64,7 @@ import com.pathplanner.lib.path.PathPlannerPath; import static com.pathplanner.lib.auto.AutoBuilder.*; import com.pathplanner.lib.auto.AutoBuilder; +import org.carlmontrobotics.subsystems.Led; //java import java.util.function.DoubleSupplier; @@ -79,8 +80,8 @@ public class RobotContainer { // 2. Use absolute paths from constants to reduce confusion public final GenericHID driverController = new GenericHID(OI.Driver.port); public final GenericHID manipulatorController = new GenericHID(OI.Manipulator.port); - private final IntakeShooter intakeShooter = new IntakeShooter(); + private final Led led = new Led(intakeShooter); private final Arm arm = new Arm(); private final Drivetrain drivetrain = new Drivetrain(); private final AuxSystems auxSystems = new AuxSystems(arm, intakeShooter); diff --git a/src/main/java/org/carlmontrobotics/commands/Intake.java b/src/main/java/org/carlmontrobotics/commands/Intake.java index 58b9634f..6ec4ab85 100644 --- a/src/main/java/org/carlmontrobotics/commands/Intake.java +++ b/src/main/java/org/carlmontrobotics/commands/Intake.java @@ -4,22 +4,27 @@ import static org.carlmontrobotics.Constants.Led.*; import org.carlmontrobotics.Constants; -import org.carlmontrobotics.subsystems.AuxSystems; + import org.carlmontrobotics.subsystems.IntakeShooter; +import org.carlmontrobotics.subsystems.Led; import edu.wpi.first.wpilibj.Timer; import edu.wpi.first.wpilibj2.command.Command; +import edu.wpi.first.wpilibj2.command.Subsystem; public class Intake extends Command { //intake until sees game peice or 4sec has passed - private final Timer timer = new Timer(); + private Timer timer; private final IntakeShooter intake; + private double endAt = 0; private final double keepIntakingFor = 0.2; int increaseAmount = 750; int index = 0; public Intake(IntakeShooter intake) { addRequirements(this.intake = intake); + + } @Override @@ -37,12 +42,14 @@ public void initialize() { public void execute() { //Intake Led if (intake.intakeDetectsNote() && !intake.outakeDetectsNote()) { - index++; + index ++; + intake.setRPMIntake(0); intake.setRPMIntake(INTAKE_SLOWDOWN_RPM + index*increaseAmount); } if (intake.outakeDetectsNote() ) { // Timer.delay(keepIntakingFor); + intake.setRPMIntake(0.0); } } @@ -60,5 +67,6 @@ public void end(boolean interrupted) { public boolean isFinished() { return (intake.intakeDetectsNote() && intake.outakeDetectsNote()); // || //timer.hasElapsed(MAX_SECONDS_OVERLOAD); + } } diff --git a/src/main/java/org/carlmontrobotics/commands/MoveToPos.java b/src/main/java/org/carlmontrobotics/commands/MoveToPos.java index ab026e6e..7ff11e09 100644 --- a/src/main/java/org/carlmontrobotics/commands/MoveToPos.java +++ b/src/main/java/org/carlmontrobotics/commands/MoveToPos.java @@ -5,7 +5,6 @@ import org.carlmontrobotics.Constants; import org.carlmontrobotics.subsystems.Arm; -import org.carlmontrobotics.subsystems.AuxSystems; import org.carlmontrobotics.subsystems.IntakeShooter; import edu.wpi.first.wpilibj.Timer; diff --git a/src/main/java/org/carlmontrobotics/commands/PassToIntake.java b/src/main/java/org/carlmontrobotics/commands/PassToIntake.java index b7fc27f9..e04090a7 100644 --- a/src/main/java/org/carlmontrobotics/commands/PassToIntake.java +++ b/src/main/java/org/carlmontrobotics/commands/PassToIntake.java @@ -9,7 +9,6 @@ import static org.carlmontrobotics.Constants.Led.*; import org.carlmontrobotics.Constants; -import org.carlmontrobotics.subsystems.AuxSystems; import org.carlmontrobotics.subsystems.IntakeShooter; import static org.carlmontrobotics.Constants.Effectorc.*; diff --git a/src/main/java/org/carlmontrobotics/commands/PassToOutake.java b/src/main/java/org/carlmontrobotics/commands/PassToOutake.java index f305c950..0128fcf0 100644 --- a/src/main/java/org/carlmontrobotics/commands/PassToOutake.java +++ b/src/main/java/org/carlmontrobotics/commands/PassToOutake.java @@ -9,7 +9,7 @@ import static org.carlmontrobotics.Constants.Led.*; import org.carlmontrobotics.Constants; -import org.carlmontrobotics.subsystems.AuxSystems; + import org.carlmontrobotics.subsystems.IntakeShooter; import static org.carlmontrobotics.Constants.Effectorc.*; diff --git a/src/main/java/org/carlmontrobotics/commands/RampToRPM.java b/src/main/java/org/carlmontrobotics/commands/RampToRPM.java index de5ca48b..6d5fb261 100644 --- a/src/main/java/org/carlmontrobotics/commands/RampToRPM.java +++ b/src/main/java/org/carlmontrobotics/commands/RampToRPM.java @@ -4,7 +4,7 @@ import static org.carlmontrobotics.Constants.Led.*; import org.carlmontrobotics.Constants; -import org.carlmontrobotics.subsystems.AuxSystems; + import org.carlmontrobotics.subsystems.IntakeShooter; import edu.wpi.first.wpilibj.Timer; diff --git a/src/main/java/org/carlmontrobotics/subsystems/Arm.java b/src/main/java/org/carlmontrobotics/subsystems/Arm.java index 88c08ea8..5681c25f 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Arm.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Arm.java @@ -186,7 +186,7 @@ public void periodic() { // SmartDashboard.putNumber("Arm Current", armMotor.getOutputCurrent()); // SmartDashboard.putNumber("ArmPos", getArmPos()); - double currTime = Timer.getFPGATimestamp(); + // double currTime = Timer.getFPGATimestamp(); // SmartDashboard.putNumber("Current Time", currTime); //SmartDashboard.putNumber("Last Update (s)", lastMeasuredTime); //setArmTarget(SmartDashboard.getNumber("set arm angle (rad)", 0)); @@ -205,7 +205,7 @@ public void periodic() { // when the value is different - double currentArmPos = getArmPos(); + /*double currentArmPos = getArmPos(); if (currentArmPos != lastArmPos) { lastMeasuredTime = currTime; lastArmPos = currentArmPos; @@ -223,6 +223,7 @@ public void periodic() { autoCancelArmCommand(); + */ } diff --git a/src/main/java/org/carlmontrobotics/subsystems/AuxSystems.java b/src/main/java/org/carlmontrobotics/subsystems/AuxSystems.java deleted file mode 100644 index 686517e8..00000000 --- a/src/main/java/org/carlmontrobotics/subsystems/AuxSystems.java +++ /dev/null @@ -1,222 +0,0 @@ -package org.carlmontrobotics.subsystems; -import edu.wpi.first.wpilibj2.command.SubsystemBase; -import org.carlmontrobotics.subsystems.IntakeShooter; - -import com.ctre.phoenix.led.ColorFlowAnimation; - -import edu.wpi.first.wpilibj.AddressableLED; -import edu.wpi.first.wpilibj.AddressableLEDBuffer; -import edu.wpi.first.wpilibj.util.Color; -import edu.wpi.first.wpilibj.util.Color8Bit; - -import static org.carlmontrobotics.Constants.Effectorc.*; -import static org.carlmontrobotics.Constants.Led.ledLength; -import static org.carlmontrobotics.Constants.Led.startingColor; - -import org.carlmontrobotics.Constants; -import org.carlmontrobotics.commands.Intake; -import edu.wpi.first.wpilibj.Timer; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; - - -/** - * AuxSystems contains both LED and Rumble functionality, - * and is separate because of it's special needs to take in other subsystems. -*/ -public class AuxSystems extends SubsystemBase { - private final AddressableLEDBuffer ledBuffer = new AddressableLEDBuffer(Constants.Led.ledLength); - private final AddressableLED led = new AddressableLED(Constants.Led.ledPort); - private int midpoint = (int) Math.floor(ledBuffer.getLength()/2);//rounds down - //AuxSubsystems watches the two other subsystems in order to rumble/led in peace - //public final Color8Bit defaultColor = new Color8Bit(255,0,0); - private final Arm arm; - private final IntakeShooter effector; - //for led color ramping - private Color8Bit currentColor = new Color8Bit(0,0,0); - - - private LedPoint currentPoint = new LedPoint(); - public boolean matchMode = true; - //^ whether we use normal color checking or flowing color mode - - private double rumble; - //stuf - private Color8Bit[] colorCycle = { - new Color8Bit(255,0,0),//0 red - new Color8Bit(255,127,0),//1 orange - new Color8Bit(255,255,0),//2 yellow - new Color8Bit(127,255,0), - new Color8Bit(0,255,0),//4 blue - new Color8Bit(0,255,127), - new Color8Bit(0,255,255), - new Color8Bit(0,127,255), - new Color8Bit(0,127,255), - new Color8Bit(0,0,255),//9 green - new Color8Bit(127,0,255), - new Color8Bit(255,0,255),//11 purple - new Color8Bit(255,0,127), - new Color8Bit(0,0,0)//13 black - }; - - public AuxSystems(Arm a, IntakeShooter is){ - this.arm = a; - this.effector = is; - //leds - led.setLength(ledBuffer.getLength()); - setLedColor(startingColor, 0 , ledBuffer.getLength()); - led.start(); - - - SmartDashboard.putBoolean("LED Match Mode:", matchMode); - - // int r = 0; - // int g = 0; - // int b = 0; - // //weird alex stuff - // for (int red = 0; red < 255/15; red ++){ - // for (int blue = 0; blue < 255/15; blue ++){ - // for (int green = 0; green < 255/15; green ++){ - // g +=15; - - // currentPoint = currentPoint.addnext(0.1,new Color8Bit(r,g,b)); - - // } - // g = 0; - // b +=15; - - - // } - // b = 0; - // r +=15; - - - //} - for (Color8Bit color : colorCycle){ - currentPoint = currentPoint.addnext(2,color); - - } - - - - currentPoint.start(); - } - - public void setLedColor(Color8Bit color, int start, int end) { - for (int i = start; i < end ; i++) - ledBuffer.setRGB(i, color.red, color.green, color.blue); - led.setData(ledBuffer); - } - @Override - public void periodic(){ - matchMode = SmartDashboard.getBoolean("LED Match Mode:", matchMode); - if (matchMode){ - /** LED RULES - * only intake TOF: lower yellow - * only outake TOF: upper purple - * both TOF: all green - * none: all red - */ - /** RUMBLE RULES - * at setpoint + intake TOF: rumble - * only outake TOF: rumble - * else: no rumble - * none: all red - */ - if (effector.intakeDetectsNote() && effector.outakeDetectsNote()){ - setLedColor(colorCycle[0], 0, ledLength); - }else if (effector.intakeDetectsNote()){ - setLedColor(colorCycle[13], 0, ledLength);//all black - setLedColor(colorCycle[2], 0, midpoint); - } else if (effector.outakeDetectsNote()) { - setLedColor(colorCycle[13], 0, ledLength);//all black - setLedColor(colorCycle[11], midpoint, ledLength); - } else { - setLedColor(colorCycle[0], 0, ledLength); - } - - - }else { - currentColor = currentPoint.currentDesiredColor(); - setLedColor(currentColor,0,Constants.Led.ledLength); - - - } - - - - } - - /** - * LedPoint - * - * Used to represent points of a graph of color, so that you can smoothly transition between them. - * Create an initial point by calling - * LedPoint ledpoint = new LedPoint(); - * or so, and then add points to the graph with - * ledpoint = ledpoint.addnext(2, new Color8Bit(255,0,0)); - * which would smoothly transition from black (000000) to full red (ff0000) in two seconds - * as long as you called - * setLedColor(ledpoint.currentDesiredColor() ,0,Constants.Led.ledLength); - * every periodic - */ - public class LedPoint { - public double startTime,duration; - public int r,g,b; - public LedPoint parent,child; - - //initial black null constructor - public LedPoint() { - this.parent=null; - this.startTime = Timer.getFPGATimestamp(); - this.duration = 0; - this.setColor(new Color8Bit(0,0,0)); - } - //use parent to chain points together - public LedPoint(LedPoint parent, double timeToTarget, Color8Bit color) { - this.parent=parent; - this.duration = timeToTarget; - this.setColor(color); - } - public double start(){ - double now = Timer.getFPGATimestamp(); - - if (parent!=null){ - startTime = parent.start() + parent.duration; - } else { - startTime = now; - } - return startTime; - } - //default assumes startTime is NOW - public LedPoint addnext(double timeToTarget, Color8Bit color) { - this.child = new LedPoint(this, timeToTarget, color); - return this.child; - } - - private void setColor(Color8Bit color){ - this.r=color.red; - this.g=color.green; - this.b=color.blue; - } - - public Color8Bit currentDesiredColor(){//return the color it should be now - double currTime = Timer.getFPGATimestamp(); - if (currTime Date: Tue, 26 Mar 2024 16:51:53 -0700 Subject: [PATCH 16/20] fixed robotcontainers --- src/main/java/org/carlmontrobotics/RobotContainer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/carlmontrobotics/RobotContainer.java b/src/main/java/org/carlmontrobotics/RobotContainer.java index 77621a0b..6a638d8b 100644 --- a/src/main/java/org/carlmontrobotics/RobotContainer.java +++ b/src/main/java/org/carlmontrobotics/RobotContainer.java @@ -84,7 +84,6 @@ public class RobotContainer { private final Led led = new Led(intakeShooter); private final Arm arm = new Arm(); private final Drivetrain drivetrain = new Drivetrain(); - private final AuxSystems auxSystems = new AuxSystems(arm, intakeShooter); /* These must be equal to the pathPlanner path names from the GUI! */ // Order matters - but the first one is index 1 on the physical selector - index 0 is reserved for null command. From 48638f9ab681322d6a030c39d66da091dab7c1ab Mon Sep 17 00:00:00 2001 From: Sofie Budman <105175854+sofiebudman@users.noreply.github.com> Date: Tue, 26 Mar 2024 18:55:11 -0700 Subject: [PATCH 17/20] testing stuff --- simgui.json | 2 +- .../java/org/carlmontrobotics/Constants.java | 2 +- .../org/carlmontrobotics/subsystems/Led.java | 35 ++++++++++++++----- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/simgui.json b/simgui.json index a04b8ead..99dcaf69 100644 --- a/simgui.json +++ b/simgui.json @@ -87,7 +87,7 @@ 0.0, 0.8500000238418579 ], - "height": 338 + "height": 177 } ] } diff --git a/src/main/java/org/carlmontrobotics/Constants.java b/src/main/java/org/carlmontrobotics/Constants.java index 6e739e97..cc8304bb 100644 --- a/src/main/java/org/carlmontrobotics/Constants.java +++ b/src/main/java/org/carlmontrobotics/Constants.java @@ -51,7 +51,7 @@ public static final class Led { public static final Color8Bit DEFAULT_COLOR_BLUE = new Color8Bit(0, 0, 200); - public static final Color8Bit DETECT_NOTE_ORANGE = new Color8Bit(250,140,3); + public static final Color8Bit DETECT_NOTE_YELLOW = new Color8Bit(255,255,0); public static final Color8Bit HOLDING_GREEN = new Color8Bit(0,250,0); public static final int ledPort = 0; //TODO: figure out how to get port of LED, it could be 0 or diff --git a/src/main/java/org/carlmontrobotics/subsystems/Led.java b/src/main/java/org/carlmontrobotics/subsystems/Led.java index 3af50b82..e683316d 100644 --- a/src/main/java/org/carlmontrobotics/subsystems/Led.java +++ b/src/main/java/org/carlmontrobotics/subsystems/Led.java @@ -2,6 +2,7 @@ import edu.wpi.first.wpilibj.AddressableLED; import edu.wpi.first.wpilibj.AddressableLEDBuffer; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj.util.Color8Bit; import edu.wpi.first.wpilibj2.command.SubsystemBase; @@ -14,6 +15,8 @@ public class Led extends SubsystemBase{ private final AddressableLED led = new AddressableLED(9); private final IntakeShooter intakeshooter; private int midpoint = (int)ledBuffer.getLength()/2; + private int color = 1; + //rounds down // public static final double midpoint = Math.floor(ledLength/2); //public static final int ledLength = led.getLength(); @@ -23,11 +26,13 @@ public Led(IntakeShooter intakeShooter){ this.intakeshooter = intakeShooter; led.setLength(ledBuffer.getLength()); led.setData(ledBuffer); - led.start(); + led.start(); setLedColor(DEFAULT_COLOR_BLUE, 0 , getLength()); + SmartDashboard.putNumber("color", color); } + public void setLedColor(Color8Bit color, int start, int end) { for (int i = start; i < end ; i++) ledBuffer.setRGB(i, color.red, color.green, color.blue); @@ -38,15 +43,28 @@ public int getLength(){ } @Override public void periodic(){ - System.err.println("skdjfksd"); - if (intakeshooter.intakeDetectsNote() && !intakeshooter.outakeDetectsNote()) { - setLedColor(DETECT_NOTE_ORANGE, 0, midpoint); + //System.err.println("skdjfksd"); + + //testing + if (SmartDashboard.getNumber("color", color) == 1) { + setLedColor(DETECT_NOTE_YELLOW, 0,getLength()); //when intake TOF detects, but outtake TOF does not the bottom half of the LEDs become orange } - else if(!intakeshooter.intakeDetectsNote() && intakeshooter.outakeDetectsNote()){ - setLedColor(DETECT_NOTE_ORANGE,midpoint, getLength()); - //when outtake TOF detects, but intake TOF does not the top half of the LEDs become orange + else if (SmartDashboard.getNumber("color", color) ==2) { + setLedColor(HOLDING_GREEN, 0, getLength()); + //when both TOFs detect and the end efforcter is holding the note the LEDS turn green + + } + else if (SmartDashboard.getNumber("color", color) == 3){ + setLedColor(DEFAULT_COLOR_BLUE, 0, getLength()); + //otherwise LEds are blue + } + + /*if (intakeshooter.intakeDetectsNote() && !intakeshooter.outakeDetectsNote()) { + setLedColor(DETECT_NOTE_YELLOW, 0,getLength()); + //when intake TOF detects, but outtake TOF does not the bottom half of the LEDs become orange + } else if (intakeshooter.intakeDetectsNote() && intakeshooter.outakeDetectsNote()) { setLedColor(HOLDING_GREEN, 0, getLength()); @@ -57,8 +75,7 @@ else if (intakeshooter.intakeDetectsNote() && intakeshooter.outakeDetectsNote()) setLedColor(DEFAULT_COLOR_BLUE, 0, getLength()); //otherwise LEds are blue } - - setLedColor(DEFAULT_COLOR_BLUE, 0, getLength()); + */ From 4d5f6f81434361f1c768fee21d8a4f9a87c680dc Mon Sep 17 00:00:00 2001 From: DriverStationComputer Date: Tue, 26 Mar 2024 19:08:52 -0700 Subject: [PATCH 18/20] go faster, make work --- logs/FRC_TBD_b599fae11159d54e.wpilog | Bin 0 -> 315693 bytes .../java/org/carlmontrobotics/Constants.java | 2 +- .../commands/AutoMATICALLYGetNote.java | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 logs/FRC_TBD_b599fae11159d54e.wpilog diff --git a/logs/FRC_TBD_b599fae11159d54e.wpilog b/logs/FRC_TBD_b599fae11159d54e.wpilog new file mode 100644 index 0000000000000000000000000000000000000000..4d9a46f98de9c7230a3934577497af0896e364e8 GIT binary patch literal 315693 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 0.5; + return false; + //return timer.get() >= 0.5; } } From 274810bdac619d91e011bf46fa6ca3db98d7f877 Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:32:25 -0700 Subject: [PATCH 19/20] merge --- src/main/java/org/carlmontrobotics/RobotContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/carlmontrobotics/RobotContainer.java b/src/main/java/org/carlmontrobotics/RobotContainer.java index eb9c4b21..e774e77f 100644 --- a/src/main/java/org/carlmontrobotics/RobotContainer.java +++ b/src/main/java/org/carlmontrobotics/RobotContainer.java @@ -78,7 +78,7 @@ private void setDefaultCommands() { private void setBindingsDriver() { new JoystickButton(driverController, 1).whileTrue(new AlignToApriltag(drivetrain)); //button A new JoystickButton(driverController, 2).whileTrue(new AlignToNote(drivetrain)); //button b? - new JoystickButton(driverController, 3).whileTrue(new AutoMATICALLYGetNote(drivetrain)); //button x? + new JoystickButton(driverController, 3).whileTrue(new AutoMATICALLYGetNote(drivetrain, limelight)); //button x? // reset field orientation?? // new JoystickButton(driverController, Driver.resetFieldOrientationButton).onTrue( // new InstantCommand(drivetrain::resetFieldOrientation)); From 152c3a5950bfde482b025feb5c53ddf23f5a532e Mon Sep 17 00:00:00 2001 From: stwiggy <144397102+stwiggy@users.noreply.github.com> Date: Tue, 26 Mar 2024 19:33:17 -0700 Subject: [PATCH 20/20] pls --- .../carlmontrobotics/commands/AutoMATICALLYGetNote.java | 2 +- .../org/carlmontrobotics/subsystems/IntakeShooter.java | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java diff --git a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java index 71bf465b..d3361099 100644 --- a/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java +++ b/src/main/java/org/carlmontrobotics/commands/AutoMATICALLYGetNote.java @@ -24,7 +24,7 @@ public class AutoMATICALLYGetNote extends Command { /** Creates a new AutoMATICALLYGetNote. */ private Drivetrain dt; - private IntakeShooter effector; + //private IntakeShooter effector; private Limelight ll; private Timer timer = new Timer(); diff --git a/src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java b/src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java deleted file mode 100644 index 37efb132..00000000 --- a/src/main/java/org/carlmontrobotics/subsystems/IntakeShooter.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.carlmontrobotics.subsystems; - -import edu.wpi.first.wpilibj2.command.SubsystemBase; - -public class IntakeShooter extends SubsystemBase{ - -}