Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
6 changes: 6 additions & 0 deletions src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,12 @@ public static final class ScoringConstants {
public static final double aimerkV = 1.51;
public static final double aimerkA = 0.01;

// TODO: find real values
public static final double aimerFaultkS = 0.4;
public static final double aimerFaultkG = 0.2;
public static final double aimerFaultkV = 3;
public static final double aimerFaultkA = 0.02;

public static final double shooterkP = 0.05;
public static final double shooterkI = 0.2;
public static final double shooterkD = 0.0;
Expand Down
88 changes: 83 additions & 5 deletions src/main/java/frc/robot/subsystems/scoring/AimerIOTalon.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public class AimerIOTalon implements AimerIO {
double lastPosition = 0.0;
double lastTime = Utils.getCurrentTimeSeconds();

boolean motorLeftFailure = false, motorRightFailure = false;
boolean motorCheckOverriden = false;

public AimerIOTalon() {
aimerRight.setControl(new Follower(ScoringConstants.aimLeftMotorId, true));

Expand Down Expand Up @@ -126,12 +129,81 @@ public void setFF(double kS, double kV, double kA, double kG) {
aimerRight.getConfigurator().apply(slot0);
}

private boolean checkForAimMotorFailure() {

// LEFT MOTOR
if (motorFailureCheckPair(aimerLeft, aimerRight)) {
motorLeftFailure = true;
}

// RIGHT MOTOR
if (motorFailureCheckPair(aimerRight, aimerLeft)) {
motorRightFailure = true;
}

if (!motorCheckOverriden) {
shutOffFaultyAimMotors();
}

return motorLeftFailure || motorRightFailure;
}

private boolean motorFailureCheckPair(TalonFX check, TalonFX compare) {
if (!check.isAlive()) {
// motor no longer communicating with robot
return true;
}

if (Math.abs(compare.getStatorCurrent().getValueAsDouble())
- Math.abs(check.getStatorCurrent().getValueAsDouble())
> 1
&& Math.abs(check.getMotorVoltage().getValueAsDouble()) > 0.5) {
// motor voltage is really small when it shouldn't be
return true;
}

if (Math.abs(check.getStatorCurrent().getValueAsDouble())
- Math.abs(compare.getStatorCurrent().getValueAsDouble())
> 1
&& Math.abs(check.getMotorVoltage().getValueAsDouble()) < 0.5) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some points of feedback here:

  1. These thresholds should be set as constants in Constants.java
  2. These are really tight thresholds. 1 A or 0.5 V is common to see as a difference between two motors. Would recommend a much bigger value for amps, but this should be pulled from match/robot data where the aimer motor was not connected most likely.
  3. We should add a time aspect to this. "If the motors disagree by X current for 1 cycle" will yield many false positives. Let's add that they must disagree for T time
  4. Some of this logic looks duplicated?

// motor voltage is really large when it shouldn't be
return true;
}
return false;
}

private void shutOffFaultyAimMotors() {
if (motorLeftFailure) {
aimerLeft.setVoltage(0);
}
if (motorRightFailure) {
aimerRight.setVoltage(0);
}
if (motorLeftFailure || motorRightFailure) {
setFF(
ScoringConstants.aimerFaultkS,
ScoringConstants.aimerFaultkV,
ScoringConstants.aimerFaultkA,
ScoringConstants.aimerFaultkG);
}
}

@Override
public void updateInputs(AimerIOInputs inputs) {
checkForAimMotorFailure();

if (override) {
aimerLeft.setVoltage(overrideVolts);
if (!motorLeftFailure || motorCheckOverriden) {
aimerLeft.setVoltage(overrideVolts);
} else {
aimerRight.setVoltage(overrideVolts);
}
} else {
aimerLeft.setControl(controller.withPosition(goalAngleRad));
if (!motorLeftFailure || motorCheckOverriden) {
aimerLeft.setControl(controller.withPosition(goalAngleRad));
} else {
aimerRight.setControl(controller.withPosition(goalAngleRad));
}
}

inputs.aimGoalAngleRad = goalAngleRad;
Expand All @@ -146,8 +218,14 @@ public void updateInputs(AimerIOInputs inputs) {
lastPosition = encoder.getAbsolutePosition();
inputs.aimVelocityRadPerSec = 0.0;

inputs.aimAppliedVolts = aimerLeft.getMotorVoltage().getValueAsDouble();
inputs.aimStatorCurrentAmps = aimerLeft.getStatorCurrent().getValueAsDouble();
inputs.aimSupplyCurrentAmps = aimerLeft.getSupplyCurrent().getValueAsDouble();
if (!motorLeftFailure || motorCheckOverriden) {
inputs.aimAppliedVolts = aimerLeft.getMotorVoltage().getValueAsDouble();
inputs.aimStatorCurrentAmps = aimerLeft.getStatorCurrent().getValueAsDouble();
inputs.aimSupplyCurrentAmps = aimerLeft.getSupplyCurrent().getValueAsDouble();
} else {
inputs.aimAppliedVolts = aimerRight.getMotorVoltage().getValueAsDouble();
inputs.aimStatorCurrentAmps = aimerLeft.getStatorCurrent().getValueAsDouble();
inputs.aimSupplyCurrentAmps = aimerLeft.getSupplyCurrent().getValueAsDouble();
}
}
}