2023-01-20 18:06:53 -07:00
|
|
|
package frc4388.robot.subsystems;
|
|
|
|
|
|
2023-02-09 19:13:55 -07:00
|
|
|
import com.ctre.phoenix.motorcontrol.ControlMode;
|
2023-02-28 17:47:35 -07:00
|
|
|
import com.ctre.phoenix.motorcontrol.FeedbackDevice;
|
|
|
|
|
import com.ctre.phoenix.motorcontrol.RemoteSensorSource;
|
|
|
|
|
import com.ctre.phoenix.motorcontrol.can.TalonFXConfiguration;
|
2023-01-20 18:06:53 -07:00
|
|
|
import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX;
|
2023-02-28 17:47:35 -07:00
|
|
|
import com.ctre.phoenix.sensors.CANCoder;
|
|
|
|
|
import com.ctre.phoenix.sensors.CANCoderConfiguration;
|
2023-02-09 19:13:55 -07:00
|
|
|
import frc4388.robot.Constants.ArmConstants;
|
2023-03-06 16:35:20 -07:00
|
|
|
import frc4388.robot.Constants.SwerveDriveConstants;
|
2023-02-09 19:13:55 -07:00
|
|
|
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
|
2023-03-11 14:03:36 -07:00
|
|
|
import edu.wpi.first.wpilibj2.command.InstantCommand;
|
|
|
|
|
import edu.wpi.first.wpilibj2.command.RunCommand;
|
2023-01-20 18:06:53 -07:00
|
|
|
import edu.wpi.first.wpilibj2.command.SubsystemBase;
|
|
|
|
|
|
|
|
|
|
public class Arm extends SubsystemBase {
|
2023-02-09 19:13:55 -07:00
|
|
|
private WPI_TalonFX m_tele;
|
|
|
|
|
private WPI_TalonFX m_pivot;
|
2023-02-28 17:47:35 -07:00
|
|
|
private CANCoder m_pivotEncoder;
|
|
|
|
|
private boolean m_debug;
|
2023-02-13 18:12:32 -07:00
|
|
|
|
|
|
|
|
// Moves arm to distance [dist] then returns new ang
|
2023-02-28 17:47:35 -07:00
|
|
|
public Arm(WPI_TalonFX pivot, WPI_TalonFX tele, CANCoder encoder, boolean debug) {
|
|
|
|
|
m_tele = tele;
|
|
|
|
|
m_pivot = pivot;
|
|
|
|
|
m_pivotEncoder = encoder;
|
|
|
|
|
|
2023-03-06 16:35:20 -07:00
|
|
|
tele.configFactoryDefault();
|
|
|
|
|
m_pivot.configFactoryDefault();
|
|
|
|
|
|
2023-02-28 17:47:35 -07:00
|
|
|
TalonFXConfiguration pivotConfig = new TalonFXConfiguration();
|
|
|
|
|
pivotConfig.slot0.kP = ArmConstants.kP;
|
|
|
|
|
pivotConfig.slot0.kI = ArmConstants.kI;
|
|
|
|
|
pivotConfig.slot0.kD = ArmConstants.kD;
|
|
|
|
|
|
|
|
|
|
pivotConfig.remoteFilter0.remoteSensorDeviceID = encoder.getDeviceID();
|
|
|
|
|
pivotConfig.remoteFilter0.remoteSensorSource = RemoteSensorSource.CANCoder;
|
|
|
|
|
pivotConfig.primaryPID.selectedFeedbackSensor = FeedbackDevice.RemoteSensor0;
|
2023-03-06 16:35:20 -07:00
|
|
|
m_pivot.configAllSettings(pivotConfig);
|
2023-02-28 17:47:35 -07:00
|
|
|
|
2023-03-06 16:35:20 -07:00
|
|
|
resetTeleSoftLimit();
|
2023-03-02 16:56:37 -07:00
|
|
|
|
2023-02-28 17:47:35 -07:00
|
|
|
CANCoderConfiguration config = new CANCoderConfiguration();
|
|
|
|
|
config.magnetOffsetDegrees = ArmConstants.OFFSET;
|
|
|
|
|
m_pivotEncoder.configAllSettings(config);
|
2023-03-11 14:03:36 -07:00
|
|
|
// m_pivot.configFactoryDefault();
|
|
|
|
|
// m_pivot.clearStickyFaults();
|
|
|
|
|
// m_pi
|
|
|
|
|
|
|
|
|
|
SmartDashboard.putNumber("kP Pivot", 0);
|
|
|
|
|
SmartDashboard.putNumber("kI Pivot", 0);
|
|
|
|
|
SmartDashboard.putNumber("kD Pivot", 0);
|
|
|
|
|
|
|
|
|
|
SmartDashboard.putData("Set PID", new InstantCommand(() -> {
|
|
|
|
|
TalonFXConfiguration pivotConfig_ = new TalonFXConfiguration();
|
|
|
|
|
pivotConfig_.slot0.kP = SmartDashboard.getNumber("kP Pivot", 0);
|
|
|
|
|
pivotConfig_.slot0.kI = SmartDashboard.getNumber("kI Pivot", 0);
|
|
|
|
|
pivotConfig_.slot0.kD = SmartDashboard.getNumber("kD Pivot", 0);
|
|
|
|
|
|
|
|
|
|
// pivotConfig_.remoteFilter0.remoteSensorDeviceID = encoder.getDeviceID();
|
|
|
|
|
// pivotConfig_.remoteFilter0.remoteSensorSource = RemoteSensorSource.CANCoder;
|
|
|
|
|
// pivotConfig_.configSelectedFeedbackFilter();// FeedbackDevice.RemoteSensor0;
|
|
|
|
|
m_pivot.configAllSettings(pivotConfig_);
|
|
|
|
|
m_pivot.configRemoteFeedbackFilter(encoder.getDeviceID(), RemoteSensorSource.CANCoder, 0);
|
|
|
|
|
m_pivot.configSelectedFeedbackSensor(FeedbackDevice.RemoteSensor0);
|
|
|
|
|
// m_pivot.selectProfileSlot(0, 0);
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
SmartDashboard.putData("set pos 1", new RunCommand(() -> m_pivot.set(ControlMode.Position, 225), this));
|
|
|
|
|
SmartDashboard.putData("set pos 2", new RunCommand(() -> m_pivot.set(ControlMode.Position, 135), this));
|
|
|
|
|
SmartDashboard.putData("Kill Self", new InstantCommand(() -> {}, this));
|
2023-02-09 19:13:55 -07:00
|
|
|
}
|
|
|
|
|
|
2023-02-28 17:47:35 -07:00
|
|
|
public Arm(WPI_TalonFX pivot, WPI_TalonFX tele, CANCoder encoder) {
|
|
|
|
|
this(pivot, tele, encoder, false);
|
2023-02-09 19:13:55 -07:00
|
|
|
}
|
|
|
|
|
|
2023-03-01 16:45:57 -07:00
|
|
|
public void setRotVel(double vel) {
|
2023-03-11 14:03:36 -07:00
|
|
|
m_pivot.set(ControlMode.PercentOutput, .4 * vel);
|
2023-03-01 16:45:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setTeleVel(double vel) {
|
2023-03-11 14:03:36 -07:00
|
|
|
m_tele.set(ControlMode.PercentOutput, -0.5 * vel);
|
2023-03-01 16:45:57 -07:00
|
|
|
}
|
|
|
|
|
|
2023-02-09 19:13:55 -07:00
|
|
|
public void armSetRotation(double rot) {
|
|
|
|
|
if (rot > 1 || rot < 0) return;
|
|
|
|
|
// Move arm code
|
2023-02-13 19:16:23 -07:00
|
|
|
m_pivot.set(ControlMode.Position, rot * Math.abs(ArmConstants.PIVOT_REVERSE_SOFT_LIMIT - ArmConstants.PIVOT_FORWARD_SOFT_LIMIT) +
|
2023-02-09 19:13:55 -07:00
|
|
|
ArmConstants.PIVOT_FORWARD_SOFT_LIMIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void armSetLength(double len) {
|
|
|
|
|
if (len > 1 || len < 0) return;
|
|
|
|
|
// Move arm code
|
2023-02-13 19:16:23 -07:00
|
|
|
m_tele.set(ControlMode.Position, len * Math.abs(ArmConstants.TELE_REVERSE_SOFT_LIMIT - ArmConstants.TELE_FORWARD_SOFT_LIMIT) +
|
2023-02-09 19:13:55 -07:00
|
|
|
ArmConstants.TELE_FORWARD_SOFT_LIMIT);
|
2023-02-28 17:47:35 -07:00
|
|
|
|
|
|
|
|
if (m_tele.isRevLimitSwitchClosed() == 1) {
|
|
|
|
|
m_tele.setSelectedSensorPosition(ArmConstants.TELE_REVERSE_SOFT_LIMIT);
|
|
|
|
|
} else if (m_tele.isFwdLimitSwitchClosed() == 1) {
|
|
|
|
|
m_tele.setSelectedSensorPosition(ArmConstants.TELE_FORWARD_SOFT_LIMIT);
|
|
|
|
|
}
|
2023-02-09 19:13:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double getArmLength() {
|
|
|
|
|
return (m_tele.getSelectedSensorPosition() - ArmConstants.TELE_FORWARD_SOFT_LIMIT) /
|
|
|
|
|
(ArmConstants.TELE_REVERSE_SOFT_LIMIT - ArmConstants.TELE_FORWARD_SOFT_LIMIT);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-01 16:45:57 -07:00
|
|
|
public double getArmRotation() {
|
|
|
|
|
return (m_pivotEncoder.getAbsolutePosition() - ArmConstants.PIVOT_FORWARD_SOFT_LIMIT) /
|
|
|
|
|
(ArmConstants.PIVOT_REVERSE_SOFT_LIMIT - ArmConstants.PIVOT_FORWARD_SOFT_LIMIT);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-09 19:13:55 -07:00
|
|
|
public void runPivotTele(double pivot, double tele) {
|
2023-03-02 16:56:37 -07:00
|
|
|
double rot = 0;
|
2023-02-09 19:13:55 -07:00
|
|
|
|
|
|
|
|
if (checkLimits(tele, rot)) {
|
|
|
|
|
armSetRotation(pivot);
|
|
|
|
|
armSetLength(tele);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks that an input is within bounds
|
|
|
|
|
* @param _len length from 0 to 1
|
|
|
|
|
* @param _theta radians from the zero (straight up)
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
public static boolean checkLimits(double _len, double _theta) {
|
|
|
|
|
var len = _len * (ArmConstants.MAX_ARM_LEN - ArmConstants.MIN_ARM_LEN) + ArmConstants.MIN_ARM_LEN;
|
|
|
|
|
var x = len * Math.cos(_theta);
|
|
|
|
|
var y = ArmConstants.ARM_HEIGHT + len * Math.sin(_theta);
|
|
|
|
|
|
|
|
|
|
var minHeight = Math.pow(ArmConstants.CURVE_POWER, Math.abs(x));
|
|
|
|
|
if (y < minHeight)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-06 16:35:20 -07:00
|
|
|
boolean tele_softLimit = false;
|
|
|
|
|
public void resetTeleSoftLimit() {
|
|
|
|
|
if (!tele_softLimit) {
|
|
|
|
|
var tele_soft = m_tele.getSelectedSensorPosition();
|
|
|
|
|
m_tele.configForwardSoftLimitThreshold(91000 - tele_soft);
|
|
|
|
|
m_tele.configReverseSoftLimitThreshold(tele_soft);
|
|
|
|
|
m_tele.configForwardSoftLimitEnable(true);
|
|
|
|
|
m_tele.configReverseSoftLimitEnable(true);
|
|
|
|
|
} else {
|
|
|
|
|
m_tele.configForwardSoftLimitEnable(false);
|
|
|
|
|
m_tele.configReverseSoftLimitEnable(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tele_softLimit = !tele_softLimit;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-11 14:03:36 -07:00
|
|
|
boolean resetable = true;
|
|
|
|
|
boolean tele_reset = true;
|
2023-03-06 16:35:20 -07:00
|
|
|
|
2023-02-09 19:13:55 -07:00
|
|
|
@Override
|
|
|
|
|
public void periodic() {
|
2023-03-06 16:35:20 -07:00
|
|
|
double degrees = Math.abs(m_pivotEncoder.getAbsolutePosition() - 135);
|
|
|
|
|
if (degrees < 2 && resetable) {
|
|
|
|
|
var pivot_soft = m_pivot.getSelectedSensorPosition();
|
|
|
|
|
var tele_soft = m_tele.getSelectedSensorPosition();
|
|
|
|
|
|
|
|
|
|
SmartDashboard.putNumber("start pivot", pivot_soft);
|
|
|
|
|
SmartDashboard.putNumber("start tele", tele_soft);
|
|
|
|
|
|
2023-03-11 14:03:36 -07:00
|
|
|
m_pivot.configForwardSoftLimitEnable(soft_limits);
|
|
|
|
|
m_pivot.configReverseSoftLimitEnable(soft_limits);
|
2023-03-06 16:35:20 -07:00
|
|
|
SmartDashboard.putNumber("fwd err", m_pivot.configForwardSoftLimitThreshold(1200 + pivot_soft).value);
|
|
|
|
|
SmartDashboard.putNumber("rvs err", m_pivot.configReverseSoftLimitThreshold(pivot_soft).value);
|
|
|
|
|
resetable = false;
|
|
|
|
|
} else if (degrees > 2) {
|
|
|
|
|
resetable = true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-11 14:03:36 -07:00
|
|
|
if (m_tele.isFwdLimitSwitchClosed() == 1 && tele_reset) {
|
|
|
|
|
var tele_soft = m_tele.getSelectedSensorPosition();
|
|
|
|
|
m_tele.configForwardSoftLimitThreshold(91000 - tele_soft);
|
|
|
|
|
m_tele.configReverseSoftLimitThreshold(1000 - tele_soft);
|
|
|
|
|
m_tele.configForwardSoftLimitEnable(true);
|
|
|
|
|
m_tele.configReverseSoftLimitEnable(true);
|
|
|
|
|
tele_reset = false;
|
|
|
|
|
} else if (m_tele.isFwdLimitSwitchClosed() == 0) {
|
|
|
|
|
tele_reset = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SmartDashboard.putBoolean("reverse", m_tele.isFwdLimitSwitchClosed() == 1);
|
|
|
|
|
|
2023-03-06 16:35:20 -07:00
|
|
|
double x = Math.cos(degrees);
|
2023-03-11 14:03:36 -07:00
|
|
|
// SwerveDriveConstants.ROTATION_SPEED = SwerveDriveConstants.MIN_ROT_SPEED + x * (SwerveDriveConstants.MAX_ROT_SPEED - SwerveDriveConstants.MIN_ROT_SPEED);
|
2023-03-02 16:56:37 -07:00
|
|
|
// if (m_debug)
|
|
|
|
|
// SmartDashboard.putNumber("Arm Motor", m_tele.getSelectedSensorPosition());
|
2023-03-06 16:35:20 -07:00
|
|
|
SmartDashboard.putNumber("Pivot CANCoder", m_pivotEncoder.getAbsolutePosition());
|
|
|
|
|
SmartDashboard.putNumber("Pivot IntegratedSensor", m_pivot.getSelectedSensorPosition());
|
|
|
|
|
SmartDashboard.putNumber("Telescope Encoder", m_tele.getSelectedSensorPosition());
|
2023-02-09 19:13:55 -07:00
|
|
|
}
|
2023-03-11 14:03:36 -07:00
|
|
|
|
|
|
|
|
boolean soft_limits = true;
|
|
|
|
|
public void killSoftLimits() {
|
|
|
|
|
var pivot_soft = m_pivot.getSelectedSensorPosition();
|
|
|
|
|
var tele_soft = m_tele.getSelectedSensorPosition();
|
|
|
|
|
|
|
|
|
|
SmartDashboard.putNumber("start pivot", pivot_soft);
|
|
|
|
|
SmartDashboard.putNumber("start tele", tele_soft);
|
|
|
|
|
|
|
|
|
|
m_pivot.configForwardSoftLimitEnable(!soft_limits);
|
|
|
|
|
m_pivot.configReverseSoftLimitEnable(!soft_limits);
|
|
|
|
|
SmartDashboard.putNumber("fwd err", m_pivot.configForwardSoftLimitThreshold(1200 + pivot_soft).value);
|
|
|
|
|
SmartDashboard.putNumber("rvs err", m_pivot.configReverseSoftLimitThreshold(pivot_soft).value);
|
|
|
|
|
|
|
|
|
|
soft_limits = !soft_limits;
|
|
|
|
|
}
|
2023-01-20 18:06:53 -07:00
|
|
|
}
|