Skip to content

Commit

Permalink
Merge branch 'main' into 3-add-intake-subsystem
Browse files Browse the repository at this point in the history
  • Loading branch information
a1cd authored Jan 19, 2024
2 parents b7bd8cf + 3aebb4d commit d7900e2
Show file tree
Hide file tree
Showing 21 changed files with 276 additions and 347 deletions.
13 changes: 13 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://6502.team/sponsorship', 'https://giving.veracross.com/da/give/robotics'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,7 @@ out/
simgui*.json

# Version file
src/main/java/frc/robot/BuildConstants.java
src/main/java/frc/robot/BuildConstants.java

# Network Tables and similar logs
networktables.json
2 changes: 1 addition & 1 deletion .wpilib/wpilib_preferences.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"enableCppIntellisense": false,
"currentLanguage": "java",
"projectYear": "2024",
"teamNumber": 6328
"teamNumber": 6502
}
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ plugins {
}

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

def ROBOT_MAIN_CLASS = "frc.robot.Main"
Expand Down Expand Up @@ -106,7 +106,7 @@ test {
}

// Simulation configuration (e.g. environment variables).
wpi.sim.addGui()
wpi.sim.addGui().defaultEnabled = true
wpi.sim.addDriverstation()

// Setting up my Jar File. In this case, adding all libraries into the main jar ('fat jar')
Expand Down
Empty file modified gradlew
100644 → 100755
Empty file.
8 changes: 8 additions & 0 deletions src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

package frc.robot;

import static java.lang.Math.PI;

/**
* The Constants class provides a convenient place for teams to hold robot-wide numerical or boolean
* constants. This class should not be used for any other purpose. All constants should be declared
Expand All @@ -23,6 +25,12 @@
*/
public final class Constants {
public static final Mode currentMode = Mode.SIM;
// *START OF CONSTANTS FOR SWERVE* (STILL MISSING WHEEL POSITIONS - Im not on the cad thingy so i
// cant see it)
// double WHEEL_RADIUS = 0.0508;
// double WHEEL_CIRCUMFERENCE = WHEEL_RADIUS * 2 * PI;
// double DRIVE_GEAR_RATIO = 6.75;
// double STEERING_RATIO = (150 / 7);

public static enum Mode {
/** Running on a real robot. */
Expand Down
18 changes: 10 additions & 8 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,10 @@
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import frc.robot.commands.DriveCommands;
import frc.robot.commands.FeedForwardCharacterization;
import frc.robot.subsystems.drive.Drive;
import frc.robot.subsystems.drive.GyroIO;
import frc.robot.subsystems.drive.GyroIOPigeon2;
import frc.robot.subsystems.drive.ModuleIO;
import frc.robot.subsystems.drive.ModuleIOSim;
import frc.robot.subsystems.drive.ModuleIOSparkMax;
import frc.robot.subsystems.drive.*;
import frc.robot.subsystems.feeder.Feeder;
import frc.robot.subsystems.feeder.FeederIO;
import frc.robot.subsystems.feeder.FeederIOSim;
import frc.robot.subsystems.flywheel.Flywheel;
import frc.robot.subsystems.flywheel.FlywheelIO;
import frc.robot.subsystems.flywheel.FlywheelIOSim;
Expand All @@ -47,6 +45,7 @@ public class RobotContainer {
// Subsystems
private final Drive drive;
private final Flywheel flywheel;
private final Feeder feeder;

// Controller
private final CommandXboxController controller = new CommandXboxController(0);
Expand All @@ -63,14 +62,15 @@ public RobotContainer() {
// Real robot, instantiate hardware IO implementations
drive =
new Drive(
new GyroIOPigeon2(false),
new GyroIOPigeon2(),
new ModuleIOSparkMax(0),
new ModuleIOSparkMax(1),
new ModuleIOSparkMax(2),
new ModuleIOSparkMax(3));
flywheel = new Flywheel(new FlywheelIOSparkMax());
feeder = new Feeder(new FeederIO() {});
// drive = new Drive(
// new GyroIOPigeon2(true),
// new GyroIOPigeon2(),
// new ModuleIOTalonFX(0),
// new ModuleIOTalonFX(1),
// new ModuleIOTalonFX(2),
Expand All @@ -88,6 +88,7 @@ public RobotContainer() {
new ModuleIOSim(),
new ModuleIOSim());
flywheel = new Flywheel(new FlywheelIOSim());
feeder = new Feeder(new FeederIOSim());
break;

default:
Expand All @@ -100,6 +101,7 @@ public RobotContainer() {
new ModuleIO() {},
new ModuleIO() {});
flywheel = new Flywheel(new FlywheelIO() {});
feeder = new Feeder(new FeederIO() {});
break;
}

Expand Down
64 changes: 24 additions & 40 deletions src/main/java/frc/robot/subsystems/drive/Drive.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,17 @@
import edu.wpi.first.wpilibj.DriverStation.Alliance;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.util.LocalADStarAK;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.littletonrobotics.junction.AutoLogOutput;
import org.littletonrobotics.junction.Logger;

public class Drive extends SubsystemBase {
private static final double MAX_LINEAR_SPEED = Units.feetToMeters(14.5);
private static final double TRACK_WIDTH_X = Units.inchesToMeters(25.0);
private static final double TRACK_WIDTH_Y = Units.inchesToMeters(25.0);
private static final double TRACK_WIDTH_X = Units.inchesToMeters(20.75);
private static final double TRACK_WIDTH_Y = Units.inchesToMeters(20.75);
private static final double DRIVE_BASE_RADIUS =
Math.hypot(TRACK_WIDTH_X / 2.0, TRACK_WIDTH_Y / 2.0);
private static final double MAX_ANGULAR_SPEED = MAX_LINEAR_SPEED / DRIVE_BASE_RADIUS;

public static final Lock odometryLock = new ReentrantLock();
private final GyroIO gyroIO;
private final GyroIOInputsAutoLogged gyroInputs = new GyroIOInputsAutoLogged();
private final Module[] modules = new Module[4]; // FL, FR, BL, BR
Expand Down Expand Up @@ -78,24 +75,17 @@ MAX_LINEAR_SPEED, DRIVE_BASE_RADIUS, new ReplanningConfig()),
&& DriverStation.getAlliance().get() == Alliance.Red,
this);
Pathfinding.setPathfinder(new LocalADStarAK());
//noinspection ToArrayCallWithZeroLengthArrayArgument
PathPlannerLogging.setLogActivePathCallback(
(activePath) -> {
Logger.recordOutput(
"Odometry/Trajectory", activePath.toArray(new Pose2d[activePath.size()]));
});
(activePath) ->
Logger.recordOutput(
"Odometry/Trajectory", activePath.toArray(new Pose2d[activePath.size()])));
PathPlannerLogging.setLogTargetPoseCallback(
(targetPose) -> {
Logger.recordOutput("Odometry/TrajectorySetpoint", targetPose);
});
(targetPose) -> Logger.recordOutput("Odometry/TrajectorySetpoint", targetPose));
}

public void periodic() {
odometryLock.lock(); // Prevents odometry updates while reading data
gyroIO.updateInputs(gyroInputs);
for (var module : modules) {
module.updateInputs();
}
odometryLock.unlock();
Logger.processInputs("Drive/Gyro", gyroInputs);
for (var module : modules) {
module.periodic();
Expand All @@ -109,37 +99,31 @@ public void periodic() {
}
// Log empty setpoint states when disabled
if (DriverStation.isDisabled()) {
//noinspection RedundantArrayCreation
Logger.recordOutput("SwerveStates/Setpoints", new SwerveModuleState[] {});
//noinspection RedundantArrayCreation
Logger.recordOutput("SwerveStates/SetpointsOptimized", new SwerveModuleState[] {});
}

// Update odometry
int deltaCount =
gyroInputs.connected ? gyroInputs.odometryYawPositions.length : Integer.MAX_VALUE;
SwerveModulePosition[] wheelDeltas = new SwerveModulePosition[4];
for (int i = 0; i < 4; i++) {
deltaCount = Math.min(deltaCount, modules[i].getPositionDeltas().length);
wheelDeltas[i] = modules[i].getPositionDelta();
}
for (int deltaIndex = 0; deltaIndex < deltaCount; deltaIndex++) {
// Read wheel deltas from each module
SwerveModulePosition[] wheelDeltas = new SwerveModulePosition[4];
for (int moduleIndex = 0; moduleIndex < 4; moduleIndex++) {
wheelDeltas[moduleIndex] = modules[moduleIndex].getPositionDeltas()[deltaIndex];
}

// The twist represents the motion of the robot since the last
// sample in x, y, and theta based only on the modules, without
// the gyro. The gyro is always disconnected in simulation.
var twist = kinematics.toTwist2d(wheelDeltas);
if (gyroInputs.connected) {
// If the gyro is connected, replace the theta component of the twist
// with the change in angle since the last sample.
Rotation2d gyroRotation = gyroInputs.odometryYawPositions[deltaIndex];
twist = new Twist2d(twist.dx, twist.dy, gyroRotation.minus(lastGyroRotation).getRadians());
lastGyroRotation = gyroRotation;
}
// Apply the twist (change since last sample) to the current pose
pose = pose.exp(twist);
// The twist represents the motion of the robot since the last
// loop cycle in x, y, and theta based only on the modules,
// without the gyro. The gyro is always disconnected in simulation.
var twist = kinematics.toTwist2d(wheelDeltas);
if (gyroInputs.connected) {
// If the gyro is connected, replace the theta component of the twist
// with the change in angle since the last loop cycle.
twist =
new Twist2d(
twist.dx, twist.dy, gyroInputs.yawPosition.minus(lastGyroRotation).getRadians());
lastGyroRotation = gyroInputs.yawPosition;
}
// Apply the twist (change since last loop cycle) to the current pose
pose = pose.exp(twist);
}

/**
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/frc/robot/subsystems/drive/GyroIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@
import org.littletonrobotics.junction.AutoLog;

public interface GyroIO {
default void updateInputs(GyroIOInputs inputs) {}

@AutoLog
public static class GyroIOInputs {
class GyroIOInputs {
public boolean connected = false;
public Rotation2d yawPosition = new Rotation2d();
public Rotation2d[] odometryYawPositions = new Rotation2d[] {};
public double yawVelocityRadPerSec = 0.0;
}

public default void updateInputs(GyroIOInputs inputs) {}
}
20 changes: 2 additions & 18 deletions src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,25 @@
import com.ctre.phoenix6.hardware.Pigeon2;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.util.Units;
import java.util.Queue;

/** IO implementation for Pigeon2 */
public class GyroIOPigeon2 implements GyroIO {
private final Pigeon2 pigeon = new Pigeon2(20);
private final StatusSignal<Double> yaw = pigeon.getYaw();
private final Queue<Double> yawPositionQueue;
private final StatusSignal<Double> yawVelocity = pigeon.getAngularVelocityZWorld();

public GyroIOPigeon2(boolean phoenixDrive) {
public GyroIOPigeon2() {
pigeon.getConfigurator().apply(new Pigeon2Configuration());
pigeon.getConfigurator().setYaw(0.0);
yaw.setUpdateFrequency(Module.ODOMETRY_FREQUENCY);
yaw.setUpdateFrequency(100.0);
yawVelocity.setUpdateFrequency(100.0);
pigeon.optimizeBusUtilization();
if (phoenixDrive) {
yawPositionQueue =
PhoenixOdometryThread.getInstance().registerSignal(pigeon, pigeon.getYaw());
} else {
yawPositionQueue =
SparkMaxOdometryThread.getInstance()
.registerSignal(() -> pigeon.getYaw().getValueAsDouble());
}
}

@Override
public void updateInputs(GyroIOInputs inputs) {
inputs.connected = BaseStatusSignal.refreshAll(yaw, yawVelocity).equals(StatusCode.OK);
inputs.yawPosition = Rotation2d.fromDegrees(yaw.getValueAsDouble());
inputs.yawVelocityRadPerSec = Units.degreesToRadians(yawVelocity.getValueAsDouble());

inputs.odometryYawPositions =
yawPositionQueue.stream()
.map((Double value) -> Rotation2d.fromDegrees(value))
.toArray(Rotation2d[]::new);
yawPositionQueue.clear();
}
}
37 changes: 9 additions & 28 deletions src/main/java/frc/robot/subsystems/drive/Module.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

public class Module {
private static final double WHEEL_RADIUS = Units.inchesToMeters(2.0);
public static final double ODOMETRY_FREQUENCY = 250.0;

private final ModuleIO io;
private final ModuleIOInputsAutoLogged inputs = new ModuleIOInputsAutoLogged();
Expand All @@ -37,7 +36,6 @@ public class Module {
private Double speedSetpoint = null; // Setpoint for closed loop control, null for open loop
private Rotation2d turnRelativeOffset = null; // Relative + Offset = Absolute
private double lastPositionMeters = 0.0; // Used for delta calculation
private SwerveModulePosition[] positionDeltas = new SwerveModulePosition[] {};

public Module(ModuleIO io, int index) {
this.io = io;
Expand Down Expand Up @@ -68,15 +66,9 @@ public Module(ModuleIO io, int index) {
setBrakeMode(true);
}

/**
* Update inputs without running the rest of the periodic logic. This is useful since these
* updates need to be properly thread-locked.
*/
public void updateInputs() {
io.updateInputs(inputs);
}

public void periodic() {
io.updateInputs(inputs);
//noinspection UnnecessaryCallToStringValueOf
Logger.processInputs("Drive/Module" + Integer.toString(index), inputs);

// On first cycle, reset relative turn encoder
Expand Down Expand Up @@ -107,19 +99,6 @@ public void periodic() {
+ driveFeedback.calculate(inputs.driveVelocityRadPerSec, velocityRadPerSec));
}
}

// Calculate position deltas for odometry
int deltaCount =
Math.min(inputs.odometryDrivePositionsRad.length, inputs.odometryTurnPositions.length);
positionDeltas = new SwerveModulePosition[deltaCount];
for (int i = 0; i < deltaCount; i++) {
double positionMeters = inputs.odometryDrivePositionsRad[i] * WHEEL_RADIUS;
Rotation2d angle =
inputs.odometryTurnPositions[i].plus(
turnRelativeOffset != null ? turnRelativeOffset : new Rotation2d());
positionDeltas[i] = new SwerveModulePosition(positionMeters - lastPositionMeters, angle);
lastPositionMeters = positionMeters;
}
}

/** Runs the module with the specified setpoint state. Returns the optimized state. */
Expand Down Expand Up @@ -185,16 +164,18 @@ public SwerveModulePosition getPosition() {
return new SwerveModulePosition(getPositionMeters(), getAngle());
}

/** Returns the module position delta since the last call to this method. */
public SwerveModulePosition getPositionDelta() {
var delta = new SwerveModulePosition(getPositionMeters() - lastPositionMeters, getAngle());
lastPositionMeters = getPositionMeters();
return delta;
}

/** Returns the module state (turn angle and drive velocity). */
public SwerveModuleState getState() {
return new SwerveModuleState(getVelocityMetersPerSec(), getAngle());
}

/** Returns the module position deltas received this cycle. */
public SwerveModulePosition[] getPositionDeltas() {
return positionDeltas;
}

/** Returns the drive velocity in radians/sec. */
public double getCharacterizationVelocity() {
return inputs.driveVelocityRadPerSec;
Expand Down
Loading

0 comments on commit d7900e2

Please sign in to comment.