diff --git a/src/main/java/frc4388/robot/Constants.java b/src/main/java/frc4388/robot/Constants.java index 9600169..5ae5339 100644 --- a/src/main/java/frc4388/robot/Constants.java +++ b/src/main/java/frc4388/robot/Constants.java @@ -175,11 +175,25 @@ public final class Constants { } public static final class VisionConstants { - public static final double TURN_P_VALUE = 0.8; - public static final double X_ANGLE_ERROR = 0.5; - public static final double GRAV = 385.83; - public static final double TARGET_HEIGHT = 67.5; - public static final double FOV = 29.8; //Field of view limelight + // public static final double TURN_P_VALUE = 0.8; + // public static final double X_ANGLE_ERROR = 0.5; + // public static final double GRAV = 385.83; + // public static final double TARGET_HEIGHT = 67.5; + // public static final double FOV = 29.8; //Field of view limelight public static final double LIME_ANGLE = 24.7; + + public static final String NAME = "photonCamera"; + + public static final double TARGET_HEIGHT = 8*12 + 8; // Convert to metric + public static final double TARGET_RADIUS = 4*12; // Convert to metric + public static final double H_FOV = 59.6; + public static final double V_FOV = 49.7; + public static final double LIME_VIXELS = 960; + public static final double LIME_HIXELS = 720; + + public static final double RANGE = 10; + + public static final double LIMELIGHT_RADIUS = 1.d; + public static final double SHOOTER_CORRECTION = 1.d; } } diff --git a/src/main/java/frc4388/robot/RobotContainer.java b/src/main/java/frc4388/robot/RobotContainer.java index dd05ec5..ef07b7e 100644 --- a/src/main/java/frc4388/robot/RobotContainer.java +++ b/src/main/java/frc4388/robot/RobotContainer.java @@ -64,6 +64,7 @@ import frc4388.robot.subsystems.LED; import frc4388.robot.subsystems.SwerveDrive; import frc4388.robot.subsystems.Turret; import frc4388.robot.subsystems.Vision; +import frc4388.robot.subsystems.VisionOdometry; import frc4388.utility.LEDPatterns; import frc4388.utility.ListeningSendableChooser; import frc4388.utility.PathPlannerUtil; @@ -88,8 +89,10 @@ public class RobotContainer { private final LED m_robotLED = new LED(m_robotMap.LEDController); private final BoomBoom m_robotBoomBoom = new BoomBoom(m_robotMap.shooterFalconLeft, m_robotMap.shooterFalconRight); private final Hood m_robotHood = new Hood(); - // private final Turret m_robotTurret = new Turret(m_robotMap.shooterTurret); + private final Turret m_robotTurret = new Turret(m_robotMap.shooterTurret); + private final VisionOdometry m_robotVisionOdometry = new VisionOdometry(m_robotSwerveDrive, m_robotTurret); // private final Vision m_robotVison = new Vision(m_robotTurret, m_robotBoomBoom); + /* Controllers */ private final XboxController m_driverXbox = new DeadbandedXboxController(OIConstants.XBOX_DRIVER_ID); private final XboxController m_operatorXbox = new DeadbandedXboxController(OIConstants.XBOX_OPERATOR_ID); @@ -119,7 +122,7 @@ public class RobotContainer { //Turret default command - // m_robotTurret.setDefaultCommand(new AimToCenter(m_robotTurret, m_robotSwerveDrive)); + m_robotTurret.setDefaultCommand(new AimToCenter(m_robotTurret, m_robotSwerveDrive, m_robotVisionOdometry)); m_robotSwerveDrive.setDefaultCommand( new RunCommand(() -> m_robotSwerveDrive.driveWithInput( diff --git a/src/main/java/frc4388/robot/RobotMap.java b/src/main/java/frc4388/robot/RobotMap.java index 649fcb2..4f1478f 100644 --- a/src/main/java/frc4388/robot/RobotMap.java +++ b/src/main/java/frc4388/robot/RobotMap.java @@ -136,7 +136,7 @@ public class RobotMap { public final WPI_TalonFX shooterFalconLeft = new WPI_TalonFX(ShooterConstants.SHOOTER_FALCON_LEFT_CAN_ID); public final WPI_TalonFX shooterFalconRight = new WPI_TalonFX(ShooterConstants.SHOOTER_FALCON_RIGHT_CAN_ID); - // public final CANSparkMax shooterTurret = new CANSparkMax(ShooterConstants.TURRET_MOTOR_CAN_ID, MotorType.kBrushless); + public final CANSparkMax shooterTurret = new CANSparkMax(ShooterConstants.TURRET_MOTOR_CAN_ID, MotorType.kBrushless); // Create motor CANSparkMax void configureShooterMotorControllers() { diff --git a/src/main/java/frc4388/robot/commands/AimToCenter.java b/src/main/java/frc4388/robot/commands/AimToCenter.java index 45f0998..144bb74 100644 --- a/src/main/java/frc4388/robot/commands/AimToCenter.java +++ b/src/main/java/frc4388/robot/commands/AimToCenter.java @@ -6,13 +6,16 @@ package frc4388.robot.commands; import edu.wpi.first.wpilibj2.command.CommandBase; import frc4388.robot.Constants.ShooterConstants; +import frc4388.robot.Constants.VisionConstants; import frc4388.robot.subsystems.SwerveDrive; import frc4388.robot.subsystems.Turret; +import frc4388.robot.subsystems.VisionOdometry; public class AimToCenter extends CommandBase { /** Creates a new AimWithOdometry. */ Turret m_turret; SwerveDrive m_drive; + VisionOdometry m_visionOdometry; // use odometry to find x and y later double x; @@ -21,11 +24,12 @@ public class AimToCenter extends CommandBase { // public static Gains m_aimGains; - public AimToCenter(Turret turret, SwerveDrive drive) { + public AimToCenter(Turret turret, SwerveDrive drive, VisionOdometry visionOdometry) { // Use addRequirements() here to declare subsystem dependencies. m_turret = turret; m_drive = drive; - addRequirements(m_turret, m_drive); + m_visionOdometry = visionOdometry; + addRequirements(m_turret, m_drive, m_visionOdometry); } // Called when the command is initially scheduled. @@ -40,6 +44,9 @@ public class AimToCenter extends CommandBase { public void execute() { m_targetAngle = angleToCenter(x, y, m_drive.getRegGyro().getDegrees()); m_turret.runshooterRotatePID(m_targetAngle); + + // Check if limelight is within range + m_visionOdometry.setLEDs(Math.abs(m_turret.getBoomBoomAngleDegrees() - m_targetAngle) < VisionConstants.RANGE); } public static double angleToCenter(double x, double y, double gyro) { diff --git a/src/main/java/frc4388/robot/subsystems/SwerveDrive.java b/src/main/java/frc4388/robot/subsystems/SwerveDrive.java index e29404a..c32e833 100644 --- a/src/main/java/frc4388/robot/subsystems/SwerveDrive.java +++ b/src/main/java/frc4388/robot/subsystems/SwerveDrive.java @@ -17,12 +17,14 @@ import edu.wpi.first.math.kinematics.SwerveDriveKinematics; import edu.wpi.first.math.kinematics.SwerveDriveOdometry; import edu.wpi.first.math.kinematics.SwerveModuleState; import edu.wpi.first.math.util.Units; +import edu.wpi.first.wpilibj.Timer; import edu.wpi.first.wpilibj.smartdashboard.Field2d; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import edu.wpi.first.wpilibj2.command.SubsystemBase; import frc4388.robot.Constants.OIConstants; import frc4388.robot.Constants.SwerveDriveConstants; import frc4388.utility.Gains; +import frc4388.utility.VisionObscuredException; public class SwerveDrive extends SubsystemBase { @@ -51,6 +53,7 @@ public class SwerveDrive extends SubsystemBase { below are robot specific, and should be tuned. */ public SwerveDrivePoseEstimator m_poseEstimator; public SwerveDriveOdometry m_odometry; + public VisionOdometry m_visionOdometry; public double speedAdjust = SwerveDriveConstants.JOYSTICK_TO_METERS_PER_SECOND_SLOW; public boolean ignoreAngles; @@ -227,11 +230,14 @@ public class SwerveDrive extends SubsystemBase { modules[2].getState(), modules[3].getState()); - // Also apply vision measurements. We use 0.3 seconds in the past as an example -- on - // a real robot, this must be calculated based either on latency or timestamps. - // m_poseEstimator.addVisionMeasurement( - // m_poseEstimator.getEstimatedPosition(), - // Timer.getFPGATimestamp() - 0.1); + // Also apply vision measurements if the camera can get vision + try { + m_poseEstimator.addVisionMeasurement( + m_visionOdometry.getVisionOdometry(), + Timer.getFPGATimestamp() - m_visionOdometry.getLatency()); + } catch (VisionObscuredException err) { + err.printStackTrace(); + } } /** diff --git a/src/main/java/frc4388/robot/subsystems/VisionOdometry.java b/src/main/java/frc4388/robot/subsystems/VisionOdometry.java new file mode 100644 index 0000000..29bdc18 --- /dev/null +++ b/src/main/java/frc4388/robot/subsystems/VisionOdometry.java @@ -0,0 +1,279 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc4388.robot.subsystems; + +import java.util.ArrayList; +import java.util.List; + +import org.opencv.core.Point; +import org.opencv.core.Point3; +import org.photonvision.PhotonCamera; +import org.photonvision.common.hardware.VisionLEDMode; +import org.photonvision.targeting.PhotonPipelineResult; +import org.photonvision.targeting.PhotonTrackedTarget; +import org.photonvision.targeting.TargetCorner; + +import edu.wpi.first.math.geometry.Pose2d; +import edu.wpi.first.math.geometry.Rotation2d; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import edu.wpi.first.wpilibj2.command.SubsystemBase; +import frc4388.robot.Constants.VisionConstants; +import frc4388.utility.VisionObscuredException; + +/** Represents the limelight and odometry related functionality + * @author Daniel McGrath + */ +public class VisionOdometry extends SubsystemBase { + // roborio ip & port: 10.43.88.2:1735 + private PhotonCamera m_camera; + + private SwerveDrive m_drive; + private Turret m_shooter; + + private double latency = 0; + + /** Creates a new VisionOdometry + * + * @param drive The swerve drive subsystem + * @param shooter The turret subsystem + */ + public VisionOdometry(SwerveDrive drive, Turret shooter) { + m_camera = new PhotonCamera(VisionConstants.NAME); + m_drive = drive; + m_shooter = shooter; + } + + /** Gets the vision points from the limelight + *
+ * Breaks down targets into 4 corners and uses the top 2 points
+ *
+ * @return Vision points on the rim of the target in screen space
+ */
+ public ArrayList
+ * Uses the known height of the target to project points
+ *
+ * @param points2d Vision points on the rim of the target in screen space
+ * @return Reverse 3d projected points
+ */
+ public static final ArrayList
+ * The guess is iterated by finding the current average vector error between the guess
+ * and the circlePoints, assuming that the guess should be a constant radius from each point
+ *
+ * @param guess The current estimate for the vision center
+ * @param circlePoints Vision points along the rim of the target
+ * @return The guess after iteration
+ */
+ public static final Point iterateGuess(Point guess, ArrayList