2022-01-11 11:54:44 -07:00
// 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.
2021-11-15 17:52:28 -07:00
package frc4388.robot.subsystems ;
2022-01-14 17:48:53 -07:00
import com.ctre.phoenix.sensors.WPI_PigeonIMU ;
2022-01-29 14:39:46 -07:00
import com.ctre.phoenix.sensors.PigeonIMU.FusionStatus ;
2021-11-29 17:18:31 -07:00
2022-01-18 19:53:14 -07:00
import edu.wpi.first.math.VecBuilder ;
import edu.wpi.first.math.estimator.SwerveDrivePoseEstimator ;
import edu.wpi.first.math.geometry.Pose2d ;
2022-01-24 17:00:06 -07:00
import edu.wpi.first.math.geometry.Rotation2d ;
2022-01-11 11:05:52 -07:00
import edu.wpi.first.math.geometry.Translation2d ;
import edu.wpi.first.math.kinematics.ChassisSpeeds ;
import edu.wpi.first.math.kinematics.SwerveDriveKinematics ;
2022-02-05 11:50:49 -07:00
import edu.wpi.first.math.kinematics.SwerveDriveOdometry ;
2022-01-11 11:05:52 -07:00
import edu.wpi.first.math.kinematics.SwerveModuleState ;
import edu.wpi.first.math.util.Units ;
2022-01-29 01:16:58 -07:00
import edu.wpi.first.wpilibj.smartdashboard.Field2d ;
2022-01-27 18:58:22 -07:00
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard ;
2021-12-02 17:51:06 -07:00
import edu.wpi.first.wpilibj2.command.SubsystemBase ;
2022-01-29 14:49:18 -07:00
import frc4388.robot.Constants.OIConstants ;
2021-11-15 17:52:28 -07:00
import frc4388.robot.Constants.SwerveDriveConstants ;
2021-12-16 16:22:36 -07:00
import frc4388.utility.Gains ;
2022-01-25 11:30:08 -07:00
import frc4388.utility.RobotLogger ;
2022-02-15 11:05:59 -07:00
import frc4388.utility.PathPlannerUtil.Path.Waypoint.Point ;
2022-01-11 11:05:52 -07:00
public class SwerveDrive extends SubsystemBase {
2022-01-24 19:06:28 -07:00
private SwerveModule m_leftFront ;
private SwerveModule m_leftBack ;
private SwerveModule m_rightFront ;
private SwerveModule m_rightBack ;
2022-01-11 11:05:52 -07:00
double halfWidth = SwerveDriveConstants . WIDTH / 2 . d ;
double halfHeight = SwerveDriveConstants . HEIGHT / 2 . d ;
2022-01-24 19:06:28 -07:00
2022-01-11 11:05:52 -07:00
public static Gains m_swerveGains = SwerveDriveConstants . SWERVE_GAINS ;
2022-01-12 17:04:58 -07:00
Translation2d m_frontLeftLocation = new Translation2d ( Units . inchesToMeters ( halfHeight ) , Units . inchesToMeters ( halfWidth ) ) ;
Translation2d m_frontRightLocation = new Translation2d ( Units . inchesToMeters ( halfHeight ) , Units . inchesToMeters ( - halfWidth ) ) ;
Translation2d m_backLeftLocation = new Translation2d ( Units . inchesToMeters ( - halfHeight ) , Units . inchesToMeters ( halfWidth ) ) ;
Translation2d m_backRightLocation = new Translation2d ( Units . inchesToMeters ( - halfHeight ) , Units . inchesToMeters ( - halfWidth ) ) ;
2022-01-11 19:57:50 -07:00
2022-01-29 14:39:46 -07:00
public SwerveDriveKinematics m_kinematics = new SwerveDriveKinematics ( m_frontLeftLocation , m_frontRightLocation , m_backLeftLocation , m_backRightLocation ) ;
2022-01-18 19:53:14 -07:00
2022-01-11 11:05:52 -07:00
public SwerveModule [ ] modules ;
2022-01-18 19:53:14 -07:00
public WPI_PigeonIMU m_gyro ;
2022-01-29 14:39:46 -07:00
protected FusionStatus fstatus = new FusionStatus ( ) ;
2022-01-18 19:53:14 -07:00
/* Here we use SwerveDrivePoseEstimator so that we can fuse odometry readings. The numbers used
below are robot specific, and should be tuned. */
2022-01-29 14:39:46 -07:00
public SwerveDrivePoseEstimator m_poseEstimator ;
2022-02-05 11:50:49 -07:00
public SwerveDriveOdometry m_odometry ;
2022-01-11 19:57:50 -07:00
2022-01-15 14:55:07 -07:00
public double speedAdjust = SwerveDriveConstants . JOYSTICK_TO_METERS_PER_SECOND_SLOW ;
public boolean ignoreAngles ;
2022-02-08 19:42:54 -07:00
public Rotation2d rotTarget = new Rotation2d ( ) ; ;
2022-02-11 18:59:00 -07:00
private ChassisSpeeds chassisSpeeds = new ChassisSpeeds ( ) ;
2022-01-15 14:55:07 -07:00
2022-01-29 01:16:58 -07:00
private final Field2d m_field = new Field2d ( ) ;
2022-01-24 19:06:28 -07:00
public SwerveDrive ( SwerveModule leftFront , SwerveModule leftBack , SwerveModule rightFront , SwerveModule rightBack , WPI_PigeonIMU gyro ) {
// m_leftFrontSteerMotor = leftFrontSteerMotor;
// m_leftFrontWheelMotor = leftFrontWheelMotor;
// m_rightFrontSteerMotor = rightFrontSteerMotor;
// m_rightFrontWheelMotor = rightFrontWheelMotor;
// m_leftBackSteerMotor = leftBackSteerMotor;
// m_leftBackWheelMotor = leftBackWheelMotor;
// m_rightBackSteerMotor = rightBackSteerMotor;
// m_rightBackWheelMotor = rightBackWheelMotor;
// m_leftFrontEncoder = leftFrontEncoder;
// m_rightFrontEncoder = rightFrontEncoder;
// m_leftBackEncoder = leftBackEncoder;
// m_rightBackEncoder = rightBackEncoder;
m_leftFront = leftFront ;
m_leftBack = leftBack ;
m_rightFront = rightFront ;
m_rightBack = rightBack ;
m_gyro = gyro ;
// modules = new SwerveModule[] {
// new SwerveModule(m_leftFrontWheelMotor, m_leftFrontSteerMotor, m_leftFrontEncoder, SwerveDriveConstants.LEFT_FRONT_ENCODER_OFFSET), // Front Left
// new SwerveModule(m_rightFrontWheelMotor, m_rightFrontSteerMotor, m_rightFrontEncoder, SwerveDriveConstants.RIGHT_FRONT_ENCODER_OFFSET), // Front Right
// new SwerveModule(m_leftBackWheelMotor, m_leftBackSteerMotor, m_leftBackEncoder, SwerveDriveConstants.LEFT_BACK_ENCODER_OFFSET), // Back Left
// new SwerveModule(m_rightBackWheelMotor, m_rightBackSteerMotor, m_rightBackEncoder, SwerveDriveConstants.RIGHT_BACK_ENCODER_OFFSET) // Back Right
// };
modules = new SwerveModule [ ] { m_leftFront , m_rightFront , m_leftBack , m_rightBack } ;
2022-01-22 10:10:46 -07:00
m_poseEstimator =
new SwerveDrivePoseEstimator (
m_gyro . getRotation2d ( ) ,
new Pose2d ( ) ,
m_kinematics ,
2022-02-05 11:50:49 -07:00
VecBuilder . fill ( 1 . 0 , 1 . 0 , Units . degreesToRadians ( 1 ) ) ,
VecBuilder . fill ( Units . degreesToRadians ( 1 ) ) ,
VecBuilder . fill ( 1 . 0 , 1 . 0 , Units . degreesToRadians ( 1 ) ) ) ;
m_odometry = new SwerveDriveOdometry ( m_kinematics , m_gyro . getRotation2d ( ) ) ;
2022-01-29 01:16:58 -07:00
m_gyro . reset ( ) ;
SmartDashboard . putData ( " Field " , m_field ) ;
2022-01-11 11:05:52 -07:00
}
2022-01-11 19:57:50 -07:00
//https://github.com/ZachOrr/MK3-Swerve-Example
/**
* Method to drive the robot using joystick info.
*
2022-01-14 17:48:53 -07:00
* @param speeds[0] Speed of the robot in the x direction (forward).
* @param speeds[1] Speed of the robot in the y direction (sideways).
2022-01-11 19:57:50 -07:00
* @param rot Angular rate of the robot.
* @param fieldRelative Whether the provided x and y speeds are relative to the field.
*/
2022-01-29 14:49:18 -07:00
public void driveWithInput ( double speedX , double speedY , double rot , boolean fieldRelative )
2022-01-11 19:57:50 -07:00
{
2022-01-29 14:49:18 -07:00
if ( speedX = = 0 & & speedY = = 0 & & rot = = 0 ) ignoreAngles = true ;
else ignoreAngles = false ;
Translation2d speed = new Translation2d ( speedX , speedY ) ;
double mag = speed . getNorm ( ) ;
speed = speed . times ( mag * speedAdjust ) ;
double xSpeedMetersPerSecond = - speed . getX ( ) ;
double ySpeedMetersPerSecond = speed . getY ( ) ;
SwerveModuleState [ ] states =
m_kinematics . toSwerveModuleStates (
fieldRelative
? ChassisSpeeds . fromFieldRelativeSpeeds ( xSpeedMetersPerSecond , ySpeedMetersPerSecond , rot * SwerveDriveConstants . ROTATION_SPEED , m_gyro . getRotation2d ( ) )
: new ChassisSpeeds ( xSpeedMetersPerSecond , ySpeedMetersPerSecond , rot * SwerveDriveConstants . ROTATION_SPEED ) ) ;
setModuleStates ( states ) ;
2022-01-29 14:39:46 -07:00
}
2022-02-11 18:59:00 -07:00
2022-01-30 21:27:50 -07:00
public void driveWithInput ( double leftX , double leftY , double rightX , double rightY , boolean fieldRelative )
2022-01-11 19:57:50 -07:00
{
2022-01-30 21:27:50 -07:00
ignoreAngles = leftX = = 0 & & leftY = = 0 & & rightX = = 0 & & rightY = = 0 ;
Translation2d speed = new Translation2d ( leftX , leftY ) ;
speed = speed . times ( speed . getNorm ( ) * speedAdjust ) ;
2022-01-31 19:29:00 -07:00
if ( Math . abs ( rightX ) > OIConstants . RIGHT_AXIS_DEADBAND | | Math . abs ( rightY ) > OIConstants . RIGHT_AXIS_DEADBAND )
rotTarget = new Rotation2d ( rightX , - rightY ) . minus ( new Rotation2d ( 0 , 1 ) ) ;
2022-01-30 21:27:50 -07:00
double rot = rotTarget . minus ( m_gyro . getRotation2d ( ) ) . getRadians ( ) ;
double xSpeedMetersPerSecond = - speed . getX ( ) ;
double ySpeedMetersPerSecond = speed . getY ( ) ;
2022-02-11 18:53:13 -07:00
chassisSpeeds = fieldRelative
? ChassisSpeeds . fromFieldRelativeSpeeds ( xSpeedMetersPerSecond , ySpeedMetersPerSecond , rot * SwerveDriveConstants . ROTATION_SPEED , m_gyro . getRotation2d ( ) )
: new ChassisSpeeds ( xSpeedMetersPerSecond , ySpeedMetersPerSecond , rightX * SwerveDriveConstants . ROTATION_SPEED ) ;
2022-01-30 21:27:50 -07:00
SwerveModuleState [ ] states =
m_kinematics . toSwerveModuleStates (
2022-02-11 18:53:13 -07:00
chassisSpeeds ) ;
2022-01-30 21:27:50 -07:00
setModuleStates ( states ) ;
}
2022-01-29 14:39:46 -07:00
public void setModuleStates ( SwerveModuleState [ ] desiredStates ) {
SwerveDriveKinematics . desaturateWheelSpeeds ( desiredStates , Units . feetToMeters ( SwerveDriveConstants . MAX_SPEED_FEET_PER_SEC ) ) ;
for ( int i = 0 ; i < desiredStates . length ; i + + ) {
SwerveModule module = modules [ i ] ;
SwerveModuleState state = desiredStates [ i ] ;
2022-01-31 19:46:21 -07:00
module . setDesiredState ( state , false ) ;
2022-01-14 17:48:53 -07:00
}
2022-01-11 11:05:52 -07:00
}
2022-02-15 11:05:59 -07:00
2022-01-14 21:02:15 -07:00
@Override
public void periodic ( ) {
2022-02-05 11:50:49 -07:00
// System.err.println(m_gyro.getFusedHeading() +" aaa");
2022-01-22 15:55:04 -07:00
updateOdometry ( ) ;
2022-01-14 21:02:15 -07:00
// m_gyro.setFusedHeadingToCompass();
// m_gyro.setYawToCompass();
2022-02-15 11:05:59 -07:00
Pose2d pos = m_poseEstimator . getEstimatedPosition ( ) ;
RobotLogger . getInstance ( ) . put (
/* anchorPointX */ pos . getX ( ) ,
/* anchorPointY */ pos . getY ( ) ,
/* prevControlX */ pos . getX ( ) ,
/* prevControlY */ pos . getY ( ) ,
/* nextControlX */ pos . getX ( ) ,
/* nextControlY */ pos . getY ( ) ,
/* holonomicAngle */ m_gyro . getRotation2d ( ) . getDegrees ( ) ,
/* isReversal */ false ,
/* velOverride */ null ,
/* isLocked */ false
) ;
2022-01-29 14:39:46 -07:00
SmartDashboard . putNumber ( " Pigeon Fused Heading " , m_gyro . getFusedHeading ( fstatus ) ) ;
2022-01-27 18:58:22 -07:00
SmartDashboard . putNumber ( " Pigeon Yaw " , m_gyro . getYaw ( ) ) ;
SmartDashboard . putNumber ( " Pigeon Get Angle " , m_gyro . getAngle ( ) ) ;
2022-01-29 14:39:46 -07:00
SmartDashboard . putNumber ( " Pigeon Rotation 2D " , m_gyro . getRotation2d ( ) . getDegrees ( ) ) ;
SmartDashboard . putStringArray ( " Fusion Status " , new String [ ] { " Is Fusing: " + fstatus . bIsFusing , " Is Valid: " + fstatus . bIsValid , " Heading: " + fstatus . heading } ) ;
2022-01-28 17:59:22 -07:00
// m_gyro.setStatusFramePeriod(PigeonIMU_StatusFrame.CondStatus_9_SixDeg_YPR, 1, SwerveDriveConstants.SWERVE_TIMEOUT_MS);
// m_gyro.setStatusFramePeriod(PigeonIMU_StatusFrame.CondStatus_6_SensorFusion, 1, SwerveDriveConstants.SWERVE_TIMEOUT_MS);
// m_gyro.setStatusFramePeriod(PigeonIMU_StatusFrame.CondStatus_1_General, 1, SwerveDriveConstants.SWERVE_TIMEOUT_MS);
2022-02-11 17:42:48 -07:00
// m_field.setRobotPose(m_poseEstimator.getEstimatedPosition());
2022-01-14 21:02:15 -07:00
super . periodic ( ) ;
}
2022-01-11 11:05:52 -07:00
2022-01-21 17:23:08 -07:00
/**
* Gets the distance between two given poses.
* @param p1 The first pose.
* @param p2 The second pose.
* @return Absolute distance between p1 and p2.
*/
public double distBtwPoses ( Pose2d p1 , Pose2d p2 ) {
return Math . sqrt ( Math . pow ( p1 . getX ( ) - p2 . getX ( ) , 2 ) + Math . pow ( p1 . getY ( ) - p2 . getY ( ) , 2 ) ) ;
}
2022-01-20 19:38:58 -07:00
/**
* Returns a scalar from your distance to the hub to your target distance.
*
* @param target_dist The target distance.
* @return A scalar that multiplies your distance from the hub to get your target distance.
*/
2022-01-22 15:55:04 -07:00
public Pose2d poseGivenDist ( double target_dist ) {
2022-01-20 19:38:58 -07:00
Pose2d p1 = m_poseEstimator . getEstimatedPosition ( ) ;
Pose2d p2 = SwerveDriveConstants . HUB_POSE ;
2022-01-22 15:55:04 -07:00
double scalar = target_dist / distBtwPoses ( p1 , p2 ) ;
Pose2d new_pose = new Pose2d ( p1 . getX ( ) * scalar , p1 . getY ( ) * scalar , p1 . getRotation ( ) ) ;
return new_pose ;
}
/**
* Gets the current pose of the robot.
* @return Robot's current pose.
*/
public Pose2d getOdometry ( ) {
2022-02-05 11:50:49 -07:00
// return m_odometry.getPoseMeters();
2022-01-22 15:55:04 -07:00
return m_poseEstimator . getEstimatedPosition ( ) ;
2022-01-20 19:38:58 -07:00
}
2022-01-24 17:00:06 -07:00
/**
* Resets the odometry of the robot to (x=0, y=0, theta=0).
*/
2022-01-29 14:39:46 -07:00
public void resetOdometry ( Pose2d pose ) {
2022-02-05 11:50:49 -07:00
// m_odometry.resetPosition(pose, m_gyro.getRotation2d());
2022-01-29 14:39:46 -07:00
m_poseEstimator . resetPosition ( pose , m_gyro . getRotation2d ( ) ) ;
2022-01-24 17:00:06 -07:00
}
2022-01-18 19:53:14 -07:00
/** Updates the field relative position of the robot. */
2022-02-05 10:08:37 -07:00
2022-01-18 19:53:14 -07:00
public void updateOdometry ( ) {
m_poseEstimator . update ( m_gyro . getRotation2d ( ) ,
2022-01-22 10:10:46 -07:00
modules [ 0 ] . getState ( ) ,
modules [ 1 ] . getState ( ) ,
modules [ 2 ] . getState ( ) ,
modules [ 3 ] . getState ( ) ) ;
2022-02-05 11:50:49 -07:00
// m_odometry.update( m_gyro.getRotation2d(),
// modules[0].getState(),
// modules[1].getState(),
// modules[2].getState(),
// modules[3].getState());
2022-01-18 19:53:14 -07:00
// 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.
2022-01-22 15:55:04 -07:00
// m_poseEstimator.addVisionMeasurement(
// m_poseEstimator.getEstimatedPosition(),
// Timer.getFPGATimestamp() - 0.1);
2022-01-18 19:53:14 -07:00
}
2022-02-08 19:42:54 -07:00
public void resetGyro ( ) {
m_gyro . reset ( ) ;
rotTarget = new Rotation2d ( 0 ) ;
}
2022-02-03 20:53:43 -07:00
public void stopModules ( ) {
modules [ 0 ] . stop ( ) ;
modules [ 1 ] . stop ( ) ;
modules [ 2 ] . stop ( ) ;
modules [ 3 ] . stop ( ) ;
}
2022-01-15 14:55:07 -07:00
public void highSpeed ( boolean shift ) {
if ( shift ) {
speedAdjust = SwerveDriveConstants . JOYSTICK_TO_METERS_PER_SECOND_FAST ;
}
else {
speedAdjust = SwerveDriveConstants . JOYSTICK_TO_METERS_PER_SECOND_SLOW ;
}
}
2021-11-15 17:27:14 -07:00
}