Initial Turrent Impl
This commit is contained in:
parent
2afbef5052
commit
3843744c76
|
|
@ -26,4 +26,15 @@ public final class Constants {
|
||||||
|
|
||||||
public static final RobotType CURRENT_MODE = RobotType.REAL;
|
public static final RobotType CURRENT_MODE = RobotType.REAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class TurretConstants{
|
||||||
|
|
||||||
|
public static final String kLimelightCameraName = "limelight_turret";
|
||||||
|
|
||||||
|
public static final int kRotationMotorId = 1;
|
||||||
|
public static final int kRotationEncoderId = 1;
|
||||||
|
|
||||||
|
public static final int kHoodMotorId = 2;
|
||||||
|
public static final int kHoodEncoderId = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
package frc.robot.subsystems;
|
||||||
|
|
||||||
|
import org.fairportrobotics.frc.posty.TestableSubsystem;
|
||||||
|
import org.fairportrobotics.frc.posty.test.PostTest;
|
||||||
|
import static org.fairportrobotics.frc.posty.assertions.Assertions.*;
|
||||||
|
|
||||||
|
import com.ctre.phoenix6.controls.ControlRequest;
|
||||||
|
import com.ctre.phoenix6.controls.PositionVoltage;
|
||||||
|
import com.ctre.phoenix6.hardware.TalonFX;
|
||||||
|
|
||||||
|
import edu.wpi.first.math.controller.PIDController;
|
||||||
|
import edu.wpi.first.math.controller.SimpleMotorFeedforward;
|
||||||
|
import edu.wpi.first.math.controller.proto.SimpleMotorFeedforwardProto;
|
||||||
|
import edu.wpi.first.networktables.NetworkTable;
|
||||||
|
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||||
|
import frc.robot.Constants;
|
||||||
|
|
||||||
|
public class TurretSubsystem extends TestableSubsystem {
|
||||||
|
|
||||||
|
private final double kSeekDelta = 0.1;
|
||||||
|
private final double kMinAngle = 0.0;
|
||||||
|
private final double kMaxAngle = 270;
|
||||||
|
|
||||||
|
private final double kOnTargetRange = 2.0;
|
||||||
|
|
||||||
|
private TalonFX mRotationMotor;
|
||||||
|
// TODO: Configure On device PID here
|
||||||
|
|
||||||
|
// If we can't use a talon, use control loops here
|
||||||
|
private SimpleMotorFeedforward mRotationFF = new SimpleMotorFeedforward(0, 0, 0);
|
||||||
|
private PIDController mRotationPID = new PIDController(0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
private TalonFX mHoodMotor;
|
||||||
|
|
||||||
|
private NetworkTable mCameraTrackingTable;
|
||||||
|
private PIDController mCameraTrackingPID = new PIDController(0, 0, 0);
|
||||||
|
|
||||||
|
private boolean mTrackingEnabled = true;
|
||||||
|
private TrackingState mTrackingState;
|
||||||
|
|
||||||
|
public TurretSubsystem(){
|
||||||
|
|
||||||
|
mRotationMotor = new TalonFX(Constants.TurretConstants.kRotationMotorId);
|
||||||
|
mHoodMotor = new TalonFX(Constants.TurretConstants.kHoodMotorId);
|
||||||
|
|
||||||
|
mCameraTrackingTable = NetworkTableInstance.getDefault().getTable(Constants.TurretConstants.kLimelightCameraName);
|
||||||
|
|
||||||
|
// This controller should be trying to get the tx value as close to zero as possible
|
||||||
|
mCameraTrackingPID.setSetpoint(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void periodic() {
|
||||||
|
super.periodic();
|
||||||
|
|
||||||
|
if(mTrackingEnabled){
|
||||||
|
|
||||||
|
// Values come from https://docs.limelightvision.io/docs/docs-limelight/apis/complete-networktables-api
|
||||||
|
boolean targetInView = mCameraTrackingTable.getValue("tv").getInteger() >= 1 ? true : false;
|
||||||
|
double tx = mCameraTrackingTable.getValue("tx").getDouble();
|
||||||
|
double ty = mCameraTrackingTable.getValue("ty").getDouble();
|
||||||
|
|
||||||
|
double requestPos = mRotationMotor.getPosition().getValueAsDouble();
|
||||||
|
|
||||||
|
if(!targetInView){
|
||||||
|
// We are seeking for an AprilTag
|
||||||
|
// Pan around until we find one
|
||||||
|
mTrackingState = TrackingState.SEEKING;
|
||||||
|
requestPos += kSeekDelta;
|
||||||
|
}else{
|
||||||
|
// We have target in view
|
||||||
|
if(Math.abs(tx) <= kOnTargetRange){
|
||||||
|
// The target is in view but we aren't centered on it
|
||||||
|
mTrackingState = TrackingState.TRACKING_ONTARGET;
|
||||||
|
}else{
|
||||||
|
// The target is in view and we are centered on it
|
||||||
|
mTrackingState = TrackingState.TRACKING_OFFTARGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestPos += mCameraTrackingPID.calculate(tx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap around if we go above rotations range
|
||||||
|
if(requestPos > kMaxAngle){
|
||||||
|
requestPos = kMinAngle;
|
||||||
|
}else if(requestPos < kMinAngle){
|
||||||
|
requestPos = kMaxAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRotationMotor.setControl(new PositionVoltage(requestPos));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enableTracking(){
|
||||||
|
mTrackingEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void disableTracking(){
|
||||||
|
mTrackingEnabled = false;
|
||||||
|
mTrackingState = TrackingState.DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackingState getmTrackingState(){
|
||||||
|
return mTrackingState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostTest(name = "Turret Rotation Motor Connected")
|
||||||
|
public void test_RotationsMotorConnected(){
|
||||||
|
assertThat(mRotationMotor.isConnected()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostTest(name = "Turret Hood Motor Connected")
|
||||||
|
public void test_HoodMotorConnected(){
|
||||||
|
assertThat(mHoodMotor.isConnected()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum TrackingState{
|
||||||
|
DISABLED,
|
||||||
|
SEEKING,
|
||||||
|
TRACKING_ONTARGET,
|
||||||
|
TRACKING_OFFTARGET
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue