Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Phoenix Pro features #6

Merged
merged 20 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
32d3ff0
feat: use waitForAll to get timesynced signals
mimizh2418 Jan 17, 2024
fb2088e
fix: make swerve offset units consistent, swerve offsets happen in th…
mimizh2418 Jan 17, 2024
c481a00
feat: use fused CANCoder for swerve turn position
mimizh2418 Jan 17, 2024
3be0871
bump: Phoenix 6 version
mimizh2418 Jan 17, 2024
17f2b27
Merge branch 'main' into zhangal/phoenixpro
rutmanz Jan 17, 2024
a2cf365
Merge branch 'main' into zhangal/phoenixpro
rutmanz Jan 18, 2024
de9708c
fix: import CAN_BUS constant correctly
rutmanz Jan 18, 2024
c27ed0a
fix: use Rotation2d factory methods
mimizh2418 Jan 18, 2024
ebfd6fd
Merge branch 'main' into zhangal/phoenixpro
mimizh2418 Jan 24, 2024
a1b2215
feat: refresh all signals at the same time (scuffed implementation?)
mimizh2418 Jan 27, 2024
d71c193
Merge branch 'main' into zhangal/phoenixpro
mimizh2418 Jan 27, 2024
ebc7798
feat: use pigeon instead of navx
mimizh2418 Jan 27, 2024
274729a
fix: potentially less scuffed signal refresher
mimizh2418 Jan 27, 2024
34030b1
fix+feat: signal refresher no longer static, better periodic updating…
mimizh2418 Jan 29, 2024
d2ab399
fix: don't print stack traces to declutter logs
mimizh2418 Jan 29, 2024
c797e4f
refactor: rename phoenixTimeSyncSignalRefresher to odometrySignalRefr…
mimizh2418 Jan 29, 2024
eb62f0d
Merge branch 'main' into zhangal/phoenixpro
mimizh2418 Jan 30, 2024
61f1624
AprilTag pose estimation (#18)
mimizh2418 Feb 3, 2024
7c1a531
Merge branch 'staging' into zhangal/phoenixpro
mimizh2418 Feb 3, 2024
2a5162b
fix: no duplicate constants
mimizh2418 Feb 3, 2024
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
17 changes: 2 additions & 15 deletions src/main/java/org/team1540/robot2024/subsystems/drive/Module.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ public class Module {
private final PIDController turnFeedback;
private Rotation2d angleSetpoint = null; // Setpoint for closed loop control, null for open loop
private Double speedSetpoint = null; // Setpoint for closed loop control, null for open loop
private Rotation2d turnRelativeOffset = null; // Relative + Offset = Absolute
private boolean forceTurn = false;
private double lastPositionMeters = 0.0; // Used for delta calculation

public Module(ModuleIO io, int index) {
Expand Down Expand Up @@ -55,17 +53,10 @@ public Module(ModuleIO io, int index) {

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

// On first cycle, reset relative turn encoder
// Wait until absolute angle is nonzero in case it wasn't initialized yet
if (turnRelativeOffset == null && inputs.turnAbsolutePosition.getRadians() != 0.0) {
turnRelativeOffset = inputs.turnAbsolutePosition.minus(inputs.turnPosition);
}
Logger.processInputs("Drivetrain/Module" + index, inputs);

// Run closed loop turn control
if (angleSetpoint != null) {

io.setTurnVoltage(
turnFeedback.calculate(getAngle().getRadians(), angleSetpoint.getRadians()));

Expand Down Expand Up @@ -143,11 +134,7 @@ public void setBrakeMode(boolean enabled) {
* Returns the current turn angle of the module.
*/
public Rotation2d getAngle() {
if (turnRelativeOffset == null) {
return new Rotation2d();
} else {
return inputs.turnPosition.plus(turnRelativeOffset);
}
return inputs.turnPosition;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* approximation for the behavior of the module.
*/
public class ModuleIOSim implements ModuleIO {
private final Rotation2d turnAbsoluteInitPosition = new Rotation2d(Math.random() * 2.0 * Math.PI);
private final DCMotorSim driveSim = new DCMotorSim(DCMotor.getFalcon500Foc(1), DRIVE_GEAR_RATIO, 0.025);
private final DCMotorSim turnSim = new DCMotorSim(DCMotor.getFalcon500Foc(1), TURN_GEAR_RATIO, 0.004);
private double driveAppliedVolts = 0.0;
Expand All @@ -32,8 +31,8 @@ public void updateInputs(ModuleIOInputs inputs) {
inputs.driveAppliedVolts = driveAppliedVolts;
inputs.driveCurrentAmps = Math.abs(driveSim.getCurrentDrawAmps());

inputs.turnAbsolutePosition = new Rotation2d(turnSim.getAngularPositionRad()).plus(turnAbsoluteInitPosition);
inputs.turnPosition = new Rotation2d(turnSim.getAngularPositionRad());
inputs.turnAbsolutePosition = Rotation2d.fromRadians(turnSim.getAngularPositionRad());
inputs.turnPosition = Rotation2d.fromRadians(turnSim.getAngularPositionRad());
inputs.turnVelocityRadPerSec = turnSim.getAngularVelocityRadPerSec();
inputs.turnAppliedVolts = turnAppliedVolts;
inputs.turnCurrentAmps = Math.abs(turnSim.getCurrentDrawAmps());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.team1540.robot2024.subsystems.drive;

import com.ctre.phoenix6.BaseStatusSignal;
import com.ctre.phoenix6.CANBus;
import com.ctre.phoenix6.StatusSignal;
import com.ctre.phoenix6.configs.MotorOutputConfigs;
import com.ctre.phoenix6.controls.VoltageOut;
Expand All @@ -13,6 +14,7 @@
import org.team1540.robot2024.util.swerve.SwerveFactory;

import static org.team1540.robot2024.Constants.Drivetrain.*;
import static org.team1540.robot2024.Constants.SwerveConfig.CAN_BUS;

/**
* Module IO implementation for Talon FX drive motor controller, Talon FX turn motor controller, and
Expand Down Expand Up @@ -42,47 +44,76 @@ public class ModuleIOTalonFX implements ModuleIO {
private final StatusSignal<Double> turnAppliedVolts;
private final StatusSignal<Double> turnCurrent;

private final Rotation2d absoluteEncoderOffset;
private final boolean isCANFD;

public ModuleIOTalonFX(SwerveFactory.SwerveModuleHW hw) {

driveTalon = hw.driveMotor;
turnTalon = hw.turnMotor;
cancoder = hw.cancoder;
absoluteEncoderOffset = hw.cancoderOffset;

isCANFD = CANBus.isNetworkFD(CAN_BUS);

setDriveBrakeMode(true);
setTurnBrakeMode(true);

drivePosition = driveTalon.getPosition();
driveVelocity = driveTalon.getVelocity();
driveAppliedVolts = driveTalon.getMotorVoltage();
driveCurrent = driveTalon.getStatorCurrent();
driveCurrent = driveTalon.getSupplyCurrent();

turnAbsolutePosition = cancoder.getAbsolutePosition();
turnPosition = turnTalon.getPosition();
turnVelocity = turnTalon.getVelocity();
turnAppliedVolts = turnTalon.getMotorVoltage();
turnCurrent = turnTalon.getStatorCurrent();
turnCurrent = turnTalon.getSupplyCurrent();

BaseStatusSignal.setUpdateFrequencyForAll(100.0, drivePosition, turnPosition); // Required for odometry, use faster rate
BaseStatusSignal.setUpdateFrequencyForAll(50.0, driveVelocity, driveAppliedVolts, driveCurrent, turnAbsolutePosition, turnVelocity, turnAppliedVolts, turnCurrent);
BaseStatusSignal.setUpdateFrequencyForAll(
50.0,
driveVelocity,
driveAppliedVolts,
driveCurrent,
turnAbsolutePosition,
turnVelocity,
turnAppliedVolts,
turnCurrent);
driveTalon.optimizeBusUtilization();
turnTalon.optimizeBusUtilization();
}

@Override
public void updateInputs(ModuleIOInputs inputs) {
BaseStatusSignal.refreshAll(drivePosition, driveVelocity, driveAppliedVolts, driveCurrent, turnAbsolutePosition, turnPosition, turnVelocity, turnAppliedVolts, turnCurrent);
if (isCANFD) {
BaseStatusSignal.waitForAll(0.01, drivePosition, turnPosition);
BaseStatusSignal.refreshAll(
driveVelocity,
driveAppliedVolts,
driveCurrent,
turnAbsolutePosition,
turnVelocity,
turnAppliedVolts,
turnCurrent);
} else {
BaseStatusSignal.refreshAll(
drivePosition,
driveVelocity,
driveAppliedVolts,
driveCurrent,
turnAbsolutePosition,
turnPosition,
turnVelocity,
turnAppliedVolts,
turnCurrent);
}

inputs.drivePositionRad = Units.rotationsToRadians(drivePosition.getValueAsDouble()) / DRIVE_GEAR_RATIO;
inputs.driveVelocityRadPerSec = Units.rotationsToRadians(driveVelocity.getValueAsDouble()) / DRIVE_GEAR_RATIO;
inputs.driveAppliedVolts = driveAppliedVolts.getValueAsDouble();
inputs.driveCurrentAmps = driveCurrent.getValueAsDouble();

inputs.turnAbsolutePosition = Rotation2d.fromRotations(turnAbsolutePosition.getValueAsDouble()).plus(absoluteEncoderOffset);
inputs.turnPosition = Rotation2d.fromRotations(turnPosition.getValueAsDouble() / TURN_GEAR_RATIO);
inputs.turnVelocityRadPerSec = Units.rotationsToRadians(turnVelocity.getValueAsDouble()) / TURN_GEAR_RATIO;
inputs.turnAbsolutePosition = Rotation2d.fromRotations(turnAbsolutePosition.getValueAsDouble());
inputs.turnPosition = Rotation2d.fromRotations(turnPosition.getValueAsDouble());
inputs.turnVelocityRadPerSec = Units.rotationsToRadians(turnVelocity.getValueAsDouble());
rutmanz marked this conversation as resolved.
Show resolved Hide resolved
inputs.turnAppliedVolts = turnAppliedVolts.getValueAsDouble();
inputs.turnCurrentAmps = turnCurrent.getValueAsDouble();
}
Expand Down
46 changes: 25 additions & 21 deletions src/main/java/org/team1540/robot2024/util/swerve/SwerveFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import com.ctre.phoenix6.hardware.CANcoder;
import com.ctre.phoenix6.hardware.TalonFX;
import com.ctre.phoenix6.signals.AbsoluteSensorRangeValue;
import com.ctre.phoenix6.signals.FeedbackSensorSourceValue;
import com.ctre.phoenix6.signals.InvertedValue;
import com.ctre.phoenix6.signals.SensorDirectionValue;
import edu.wpi.first.math.geometry.Rotation2d;
import static org.team1540.robot2024.Constants.SwerveConfig.CAN_BUS;;

import static org.team1540.robot2024.Constants.SwerveConfig.CAN_BUS;
import static org.team1540.robot2024.Constants.Drivetrain.TURN_GEAR_RATIO;


public class SwerveFactory {
private static final double[] moduleOffsetsRots = new double[]{
Expand All @@ -28,21 +31,20 @@ public static SwerveModuleHW getModuleMotors(int id, SwerveCorner corner) {

public enum SwerveCorner {
FRONT_LEFT(0),
FRONT_RIGHT(90),
BACK_LEFT(270),
BACK_RIGHT(180);
FRONT_RIGHT(0.25),
BACK_LEFT(0.75),
BACK_RIGHT(0.5);

private final double offset;
SwerveCorner(double offset) {
this.offset = offset;
private final double offsetRots;
SwerveCorner(double offsetRots) {
this.offsetRots = offsetRots;
}
}

public static class SwerveModuleHW {
public final TalonFX driveMotor;
public final TalonFX turnMotor;
public final CANcoder cancoder;
public final Rotation2d cancoderOffset;

private SwerveModuleHW(int id, SwerveCorner corner, String canbus) {
if (id < 1 || id > 8) {
Expand All @@ -51,6 +53,11 @@ private SwerveModuleHW(int id, SwerveCorner corner, String canbus) {
if (canbus == null) {
canbus = "";
}

int driveID = 30 + id;
int turnID = 20 + id;
int canCoderID = 10 + id;

TalonFXConfiguration driveConfig = new TalonFXConfiguration();
TalonFXConfiguration turnConfig = new TalonFXConfiguration();
CANcoderConfiguration canCoderConfig = new CANcoderConfiguration();
Expand All @@ -64,26 +71,23 @@ private SwerveModuleHW(int id, SwerveCorner corner, String canbus) {
turnConfig.CurrentLimits.SupplyCurrentLimit = 30.0;
turnConfig.CurrentLimits.SupplyCurrentLimitEnable = true;
turnConfig.MotorOutput.Inverted = InvertedValue.Clockwise_Positive;
turnConfig.Feedback.FeedbackRemoteSensorID = canCoderID;
turnConfig.Feedback.FeedbackSensorSource = FeedbackSensorSourceValue.FusedCANcoder;
turnConfig.Feedback.SensorToMechanismRatio = 1.0;
turnConfig.Feedback.RotorToSensorRatio = TURN_GEAR_RATIO;

canCoderConfig.MagnetSensor.MagnetOffset = moduleOffsetsRots[id-1];
canCoderConfig.MagnetSensor.MagnetOffset = moduleOffsetsRots[id-1] + corner.offsetRots;
canCoderConfig.MagnetSensor.SensorDirection = SensorDirectionValue.CounterClockwise_Positive;
canCoderConfig.MagnetSensor.AbsoluteSensorRange = AbsoluteSensorRangeValue.Unsigned_0To1;

this.driveMotor = new TalonFX(30 + id, canbus);
this.driveMotor = new TalonFX(driveID, canbus);
this.driveMotor.getConfigurator().apply(driveConfig);

this.turnMotor = new TalonFX(20 + id, canbus);

this.turnMotor.getConfigurator().apply(turnConfig);

this.cancoder = new CANcoder(10 + id, canbus);


this.cancoder = new CANcoder(canCoderID, canbus);
this.cancoder.getConfigurator().apply(canCoderConfig);

this.cancoderOffset = Rotation2d.fromDegrees(corner.offset);


this.turnMotor = new TalonFX(turnID, canbus);
this.turnMotor.getConfigurator().apply(turnConfig);
}
}
}
Loading