Skip to content
This repository has been archived by the owner on Jan 24, 2023. It is now read-only.

Swerve drive proto #6

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
845a5c3
Climber PID magik
WAaron-500 Apr 28, 2022
cbbe3c6
add yml file lol
WAaron-500 Apr 28, 2022
8853567
moved utils to seperate package lol
WAaron-500 May 1, 2022
8b9a8ee
PID tuning things
WAaron-500 May 12, 2022
b0f47c5
clean up
WAaron-500 May 12, 2022
bbbd249
added something to enable/disable tuning bc I forgor to do that
WAaron-500 May 12, 2022
11b909a
use listners
WAaron-500 May 12, 2022
537260c
fixes + ankit mode
WAaron-500 May 12, 2022
8c14106
very bad documentation
WAaron-500 May 12, 2022
a82fcaa
remove meme
WAaron-500 May 18, 2022
83e3315
Nick Fixes 1,2, and kind of 4
WAaron-500 May 19, 2022
e015f10
more fixes and clean up
WAaron-500 May 19, 2022
1945e08
clean up bad math and add some documentation
WAaron-500 May 19, 2022
d5602ba
used slotIdx
WAaron-500 May 20, 2022
2cb781a
proof of concept
WAaron-500 May 20, 2022
a1bd5d6
basis of a swerve drive
WAaron-500 May 20, 2022
ea3c652
command maybe?
WAaron-500 May 20, 2022
077f187
command maybe p2
WAaron-500 May 20, 2022
d4a15c9
fix redundancies
WAaron-500 May 20, 2022
8c32b33
fix redundant
WAaron-500 May 20, 2022
71176c0
fix index
WAaron-500 May 20, 2022
d9db0bd
fix thing
WAaron-500 May 20, 2022
9cc4e17
forgor a -1
WAaron-500 May 20, 2022
bfb4c98
fixed typo, and reorganized the util file per Nick's suggestion.
WAaron-500 May 20, 2022
3571e1a
haha graphs go brrrrrrr
WAaron-500 May 20, 2022
2034444
optomization of wheels
WAaron-500 May 20, 2022
989c4ca
must write code... braine shriveling bc no off season
WAaron-500 Jun 1, 2022
88b51f3
Cancoder and Sparkmax courtesy of Jakson
WAaron-500 Jun 6, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Build

on:
push:
pull_request:

jobs:
build:
name: Build
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2022-18.04
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Grant execute permission
run: chmod +x gradlew
- name: Build robot code
run: ./gradlew build
139 changes: 139 additions & 0 deletions src/main/java/frc/mechtechsupport/modules/SwerveModuleConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package frc.mechtechsupport.modules;

import com.ctre.phoenix.motorcontrol.ControlMode;
import com.ctre.phoenix.motorcontrol.TalonFXSensorCollection;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX;

import edu.wpi.first.math.kinematics.SwerveModuleState;
import frc.mechtechsupport.util.SwerveModuleMath;
import frc.mechtechsupport.util.TalonFXUtils;
import frc.robot.Constants;

public class SwerveModuleConfig {
//Module Variables
private final int idDrive;
private final int idSteer;
private final double degOffSet;

//Drive objects for the Module
private final WPI_TalonFX drive;
private TalonFXSensorCollection driveEncoder;

//Steering objects for the Module (encoder will be analogInput OR canCoder)
private final WPI_TalonFX steer;
private TalonFXSensorCollection steerEncoder;

//PID Vars
private double kPSteer;
private double kISteer;
private double kDSteer;
private double kFSteer;
private double kPDrive;
private double kIDrive;
private double kDDrive;
private double kFDrive;

public SwerveModuleConfig(int idDrive, int idSteer, double degOffSet, double kPSteer,
double kISteer, double kDSteer, double kFSteer, double kPDrive, double kIDrive, double kDDrive,
double kFDrive) {
this.idDrive = idDrive;
this.idSteer = idSteer;
this.degOffSet = degOffSet;
this.kPSteer = kPSteer;
this.kISteer = kISteer;
this.kDSteer = kDSteer;
this.kFSteer = kFSteer;
this.kPDrive = kPDrive;
this.kIDrive = kIDrive;
this.kDDrive = kDDrive;
this.kFDrive = kFDrive;

//Motor Config
drive = new WPI_TalonFX(idDrive);
steer = new WPI_TalonFX(idSteer);

//PID Config
drive.config_kP(0, kPDrive);
drive.config_kI(0, kIDrive);
drive.config_kD(0, kDDrive);
drive.config_kF(0, kFDrive);
steer.config_kP(0, kPSteer);
steer.config_kI(0, kISteer);
steer.config_kD(0, kDSteer);
steer.config_kF(0, kFSteer);

//Encoder Config
driveEncoder = drive.getSensorCollection();
steerEncoder = steer.getSensorCollection();
}

public void configSteerPID(double kp, double ki, double kd, double kf) {
steer.config_kP(0, kp);
steer.config_kI(0, ki);
steer.config_kD(0, kd);
steer.config_kF(0, kf);
}

public void configDrivePID(double kp, double ki, double kd, double kf) {
steer.config_kP(0, kp);
steer.config_kI(0, ki);
steer.config_kD(0, kd);
steer.config_kF(0, kf);
}

public double getDriveVelocity() {
return driveEncoder.getIntegratedSensorVelocity();
}

public double getAbsoluteEncoderRad() {
return Math.toRadians(getAngle());
}

public void setSteer(double heading) {
steer.set(ControlMode.Position,
TalonFXUtils.wheelDegreesToTicks(SwerveModuleMath.boundPM180(heading), Constants.steerGearRatio));
}

public void setDrive(double speed) {
steer.set(ControlMode.Velocity, speed);
}

public void setDesiredState(SwerveModuleState state) {
if (Math.abs(state.speedMetersPerSecond) < 0.01) {
steer.set(0);
drive.set(0);
return;
}
double target = state.angle.getDegrees();
double angle = SwerveModuleMath.boundPM180(target - getAngle());
double invAngle = SwerveModuleMath.boundPM180(target + 180 - getAngle());
double optomizedAngleMagnitude = Math.min(Math.abs(angle), Math.abs(invAngle));
if (Math.abs(angle) != optomizedAngleMagnitude) {
double pos = steer.getSelectedSensorPosition() + (invAngle) * (Constants.encoderTalonFXTicksPerRev / 360);
steer.set(ControlMode.Position, pos);
drive.set(ControlMode.Velocity, -state.speedMetersPerSecond);
} else {
double pos = steer.getSelectedSensorPosition() + (angle) * (Constants.encoderTalonFXTicksPerRev / 360);
steer.set(ControlMode.Position, pos);
drive.set(ControlMode.Velocity, state.speedMetersPerSecond);
}
}

public void resetEncoders() {
driveEncoder.setIntegratedSensorPosition(0, 0);
}

public double getAngle() {
double ang = steerEncoder.getIntegratedSensorPosition();
ang = ang * 360 / Constants.encoderTalonFXTicksPerRev + degOffSet; //Compassify
if (ang > 360) {
ang -= 360;
}
return ang;
}

public void stop() {
drive.set(0);
steer.set(0);
}
}
25 changes: 25 additions & 0 deletions src/main/java/frc/mechtechsupport/modules/SwerveOdometer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package frc.mechtechsupport.modules;

import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Translation2d;

/**
* Keeps track of the robot position relative to the field
*/
public class SwerveOdometer {
public double x = 0, y = 0;

public void update(double x, double y) {
this.x += x;
this.y += y;
}

public Translation2d getPoseMeters() {
return new Translation2d(x, y);
}

public void resetPosition(Pose2d pose2d) {
x = pose2d.getX();
y = pose2d.getY();
}
}
127 changes: 127 additions & 0 deletions src/main/java/frc/mechtechsupport/util/PIDTuning.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package frc.mechtechsupport.util;

import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import frc.mechtechsupport.modules.SwerveModuleConfig;
import frc.robot.Constants;

public class PIDTuning {
//TODO: make PID Tuner for swerve
private static double errorVel;
private static double setPointVel;
private static double errorPos;
private static double setPointPos;
private static SwerveModuleConfig module;
private static double pSteer = 0;
private static double iSteer = 0;
private static double dSteer = 0;
private static double fSteer = 0;
private static double pDrive = 0;
private static double iDrive = 0;
private static double dDrive = 0;
private static double fDrive = 0;
private static int driveID = 0;
private static int steerID = 0;
private static TunableNumber tunableSteerP;
private static TunableNumber tunableSteerI;
private static TunableNumber tunableSteerD;
private static TunableNumber tunableSteerF;
private static TunableInt tunableSteerID;
private static TunableNumber tunableHeading;
private static TunableNumber tunableDriveP;
private static TunableNumber tunableDriveI;
private static TunableNumber tunableDriveD;
private static TunableNumber tunableDriveF;
private static TunableInt tunableDriveID;
private static TunableNumber tunableSpeed;

public PIDTuning() {
if (Constants.tuningMode) {
module = new SwerveModuleConfig(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

errorVel = 0;
setPointVel = 0;
errorPos = 0;
setPointPos = 0;
tunableNumberInit();
shuffleboardMagik();
changeListener();
} else {
return;
}
}

public void shuffleboardMagik() {
if (Constants.tuningMode) {
SmartDashboard.putNumber("Velocity Error", errorVel);
SmartDashboard.putNumber("Velocity Set Point", setPointVel);
SmartDashboard.putNumber("Position Error", errorPos);
SmartDashboard.putNumber("Position Set Point", setPointPos);
} else {
return;
}
}

private void tunableNumberInit() {
tunableSteerID = new TunableInt("Steer Motor ID", 0);
tunableDriveID = new TunableInt("Drive Motor ID", 0);
tunableSteerP = new TunableNumber("Steer Motor P Gain", 0);
tunableDriveP = new TunableNumber("Drive Motor P Gain", 0);
tunableSteerI = new TunableNumber("Steer Motor I Gain", 0);
tunableDriveI = new TunableNumber("Drive Motor I Gain", 0);
tunableSteerD = new TunableNumber("Steer Motor D Gain", 0);
tunableDriveD = new TunableNumber("Drive Motor D Gain", 0);
tunableSteerF = new TunableNumber("Steer Motor F Gain", 0);
tunableDriveF = new TunableNumber("Drive Motor F Gain", 0);
tunableHeading = new TunableNumber("Heading set point", 0);
tunableSpeed = new TunableNumber("Speed set point", 0);
}

private void changeListener() {
tunableSteerID.addChangeListener((val) -> module = new SwerveModuleConfig(driveID, val, 0.0, pSteer,
iSteer, dSteer, fSteer, pDrive, iDrive, dDrive, fDrive));
tunableDriveID.addChangeListener((val) -> module = new SwerveModuleConfig(val, steerID, 0.0, pSteer,
iSteer, dSteer, fSteer, pDrive, iDrive, dDrive, fDrive));
tunableSteerP.addChangeListener((val) -> module.configSteerPID(val, iSteer, dSteer, fSteer));
tunableDriveP.addChangeListener((val) -> module.configDrivePID(val, iDrive, dDrive, fDrive));
tunableSteerI.addChangeListener((val) -> module.configSteerPID(pSteer, val, dSteer, fSteer));
tunableDriveI.addChangeListener((val) -> module.configDrivePID(pDrive, val, dDrive, fDrive));
tunableSteerD.addChangeListener((val) -> module.configSteerPID(pSteer, iSteer, val, fSteer));
tunableDriveD.addChangeListener((val) -> module.configDrivePID(pDrive, iDrive, val, fDrive));
tunableSteerF.addChangeListener((val) -> module.configSteerPID(pSteer, iSteer, dSteer, val));
tunableDriveF.addChangeListener((val) -> module.configDrivePID(pDrive, iDrive, dDrive, val));
tunableHeading.addChangeListener((val) -> module.setSteer(val));
tunableSpeed.addChangeListener((val) -> module.setDrive(val));
}

public void Tune() {
if (Constants.tuningMode) {
pSteer = tunableSteerP.get();
iSteer = tunableSteerI.get();
dSteer = tunableSteerD.get();
fSteer = tunableSteerF.get();
pDrive = tunableDriveP.get();
iDrive = tunableDriveI.get();
dDrive = tunableDriveD.get();
fDrive = tunableDriveF.get();
driveID = tunableDriveID.get();
steerID = tunableSteerID.get();
setPointVel = tunableSpeed.get();
setPointPos = tunableHeading.get();
errorVel = setPointVel - module.getDriveVelocity();
errorPos = setPointPos - module.getAngle();
}
}

public void printFeeds() {
if (Constants.tuningMode) {
System.out.println("Steer P Gain" + pSteer);
System.out.println("Steer I Gain" + iSteer);
System.out.println("Steer D Gain" + dSteer);
System.out.println("Steer F Gain" + fSteer);
System.out.println("Drive P Gain" + pDrive);
System.out.println("Drive I Gain" + iDrive);
System.out.println("Drive D Gain" + dDrive);
System.out.println("Drive F Gain" + fDrive);
}
}
}
69 changes: 69 additions & 0 deletions src/main/java/frc/mechtechsupport/util/SwerveModuleMath.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package frc.mechtechsupport.util;

import edu.wpi.first.math.geometry.Translation2d;
import edu.wpi.first.math.kinematics.SwerveDriveKinematics;
import edu.wpi.first.math.util.Units;

public class SwerveModuleMath {
public static double restrictAngle(double angle) {
while (angle > 360) {
angle -= 360;
}
while (angle < 0) {
angle += 360;
}
return angle;
}

public static final SwerveDriveKinematics swerveMagik = new SwerveDriveKinematics(
new Translation2d(Units.inchesToMeters(24) / 2, Units.inchesToMeters(24) / 2), //FR
new Translation2d(Units.inchesToMeters(24) / 2, -Units.inchesToMeters(24) / 2), //FL
new Translation2d(-Units.inchesToMeters(24) / 2, Units.inchesToMeters(24) / 2), //BR
new Translation2d(-Units.inchesToMeters(24) / 2, -Units.inchesToMeters(24) / 2) //BL
WAaron-500 marked this conversation as resolved.
Show resolved Hide resolved
);

public static double boundPM180(double angle) {
while (angle >= 180.0)
angle -= 360.0;
while (angle < -180.0)
angle += 360.0;
return angle;
}

public static double getXHeading(double angle) {
while (angle > 360) {
angle -= 360;
}
while (angle < 0) {
angle += 360;
}

if (angle >= 0 && angle <= 90) {
return Math.cos(Math.toRadians(90 - angle));
} else if (angle >= 270 && angle <= 360) {
return -Math.cos(Math.toRadians(270 - angle));
} else if (angle >= 90 && angle <= 270) {
return Math.cos(-Math.toRadians(angle - 90));
}

return 0.0;
}

public static double getYHeading(double angle) {
while (angle > 360) {
angle -= 360;
}
while (angle < 0) {
angle += 360;
}

if (angle >= 0 && angle <= 90) {
return Math.sin(Math.toRadians(90 - angle));
} else if (angle >= 270 && angle <= 360) {
return -Math.sin(Math.toRadians(270 - angle));
} else if (angle >= 90 && angle <= 270) {
return Math.sin(-Math.toRadians(angle - 90));
}
return 0.0;
}
}
Loading