背板完成

This commit is contained in:
OnDYCLaptop
2026-07-09 11:58:36 +08:00
parent 1c39a3bc42
commit 914584b71c
3 changed files with 63 additions and 20 deletions
+7 -2
View File
@@ -53,8 +53,13 @@ public final class Constants {
public static final double kD = 0.0; public static final double kD = 0.0;
} }
public static final double backboardSpeedMax = 5.0; public static final double backboardSpeedMax = 3.0;
public static final double backboardSpeedMin = 0.4; public static final double backboardSpeedMin = 0;
public static final double backboardGravityFeedforwardMinVolts = 0.1;
public static final double backboardGravityFeedforwardMaxVolts = 0.3;
public static final double backboardGravityFeedforwardMinPosition = 0.0;
public static final double backboardGravityFeedforwardMaxPosition = 2200.0;
public static final double backboardGravityFeedforwardDirection = 1.0;
public static final double backboardUpLimit = 2200.0; public static final double backboardUpLimit = 2200.0;
public static final double backboardDownLimit = 0.0; public static final double backboardDownLimit = 0.0;
} }
@@ -54,6 +54,7 @@ public class ShooterSubsystem extends SubsystemBase {
private double shooterConveyorOutputVolts = 0.0; private double shooterConveyorOutputVolts = 0.0;
private double backboardOutputVolts = 0.0; private double backboardOutputVolts = 0.0;
private double backboardRawPidOutputVolts = 0.0; private double backboardRawPidOutputVolts = 0.0;
private double backboardGravityFeedforwardVolts = 0.0;
private double backboardClampedPidOutputVolts = 0.0; private double backboardClampedPidOutputVolts = 0.0;
private boolean backboardOutputSaturated = false; private boolean backboardOutputSaturated = false;
private boolean backboardMinimumOutputActive = false; private boolean backboardMinimumOutputActive = false;
@@ -203,7 +204,8 @@ public class ShooterSubsystem extends SubsystemBase {
public void outputBackboard() { public void outputBackboard() {
// 背板仍使用旧外部编码器和 ProfiledPID;Superstructure 只选择目标位置。 // 背板仍使用旧外部编码器和 ProfiledPID;Superstructure 只选择目标位置。
double rawPidOutput = backboardPID.calculate(getBackboardPosition()); double backboardPosition = getBackboardPosition();
double rawPidOutput = backboardPID.calculate(backboardPosition);
double pidOutput = MathUtil.clamp( double pidOutput = MathUtil.clamp(
rawPidOutput, rawPidOutput,
-Constants.Shooter.backboardSpeedMax, -Constants.Shooter.backboardSpeedMax,
@@ -220,26 +222,50 @@ public class ShooterSubsystem extends SubsystemBase {
backboardMinimumOutputActive = false; backboardMinimumOutputActive = false;
} }
shooterNetworkTable.getEntry("backboardPIDOutput").setDouble(pidOutput); double gravityOutput = calculateBackboardGravityFeedforward(backboardPosition);
setBackboardVoltage(pidOutput); double outputVolts = MathUtil.clamp(
pidOutput + gravityOutput,
-Constants.Shooter.backboardSpeedMax,
Constants.Shooter.backboardSpeedMax
);
backboardGravityFeedforwardVolts = gravityOutput;
backboardOutputSaturated = backboardOutputSaturated
|| Math.abs((pidOutput + gravityOutput) - outputVolts) > 1e-9;
shooterNetworkTable.getEntry("backboardPIDOutput").setDouble(outputVolts);
setBackboardVoltage(outputVolts);
}
private double calculateBackboardGravityFeedforward(double backboardPosition) {
double clampedPosition = MathUtil.clamp(
backboardPosition,
Constants.Shooter.backboardGravityFeedforwardMinPosition,
Constants.Shooter.backboardGravityFeedforwardMaxPosition
);
double positionRange = Constants.Shooter.backboardGravityFeedforwardMaxPosition
- Constants.Shooter.backboardGravityFeedforwardMinPosition;
if (positionRange <= 0.0) {
return 0.0;
}
double positionRatio = (clampedPosition - Constants.Shooter.backboardGravityFeedforwardMinPosition)
/ positionRange;
double feedforwardVolts = Constants.Shooter.backboardGravityFeedforwardMinVolts
+ positionRatio
* (Constants.Shooter.backboardGravityFeedforwardMaxVolts
- Constants.Shooter.backboardGravityFeedforwardMinVolts);
return Constants.Shooter.backboardGravityFeedforwardDirection * feedforwardVolts;
} }
public void holdBackboardAt(double targetPosition) { public void holdBackboardAt(double targetPosition) {
// 上层只给目标位置;到位后停止输出,未到位时继续闭环。 // 上层只给目标位置;到位后仍继续输出重力补偿。
setBackboardPosition(targetPosition); setBackboardPosition(targetPosition);
if (isBackboardAtTarget()) {
backboardRawPidOutputVolts = 0.0;
backboardClampedPidOutputVolts = 0.0;
backboardOutputSaturated = false;
backboardMinimumOutputActive = false;
setBackboardVoltage(0.0);
} else {
outputBackboard(); outputBackboard();
} }
}
public void stopBackboard() { public void stopBackboard() {
backboardRawPidOutputVolts = 0.0; backboardRawPidOutputVolts = 0.0;
backboardGravityFeedforwardVolts = 0.0;
backboardClampedPidOutputVolts = 0.0; backboardClampedPidOutputVolts = 0.0;
backboardOutputSaturated = false; backboardOutputSaturated = false;
backboardMinimumOutputActive = false; backboardMinimumOutputActive = false;
@@ -254,6 +280,10 @@ public class ShooterSubsystem extends SubsystemBase {
return backboardPID.atGoal(); return backboardPID.atGoal();
} }
public boolean isBackboardPositionTuningActive() {
return backboardTuningTable.getEntry("backboardPositionEnable").getBoolean(false);
}
public void resetbackboardencoder() { public void resetbackboardencoder() {
backboardEncoder.reset(); backboardEncoder.reset();
backboardPID.reset(0); backboardPID.reset(0);
@@ -301,7 +331,6 @@ public class ShooterSubsystem extends SubsystemBase {
@Override @Override
public void periodic() { public void periodic() {
backboardPID.calculate(getBackboardPosition());
double backboardPosition = getBackboardPosition(); double backboardPosition = getBackboardPosition();
double backboardGoalPosition = backboardPID.getGoal().position; double backboardGoalPosition = backboardPID.getGoal().position;
double backboardSetpointPosition = backboardPID.getSetpoint().position; double backboardSetpointPosition = backboardPID.getSetpoint().position;
@@ -324,11 +353,14 @@ public class ShooterSubsystem extends SubsystemBase {
shooterNetworkTable.getEntry("backboardGoalError").setDouble(backboardGoalPosition - backboardPosition); shooterNetworkTable.getEntry("backboardGoalError").setDouble(backboardGoalPosition - backboardPosition);
shooterNetworkTable.getEntry("backboardSetpointError").setDouble(backboardSetpointPosition - backboardPosition); shooterNetworkTable.getEntry("backboardSetpointError").setDouble(backboardSetpointPosition - backboardPosition);
shooterNetworkTable.getEntry("backboardRawPIDOutput").setDouble(backboardRawPidOutputVolts); shooterNetworkTable.getEntry("backboardRawPIDOutput").setDouble(backboardRawPidOutputVolts);
shooterNetworkTable.getEntry("backboardGravityFeedforward").setDouble(backboardGravityFeedforwardVolts);
shooterNetworkTable.getEntry("backboardClampedPIDOutput").setDouble(backboardClampedPidOutputVolts); shooterNetworkTable.getEntry("backboardClampedPIDOutput").setDouble(backboardClampedPidOutputVolts);
shooterNetworkTable.getEntry("backboardOutputSaturated").setBoolean(backboardOutputSaturated); shooterNetworkTable.getEntry("backboardOutputSaturated").setBoolean(backboardOutputSaturated);
shooterNetworkTable.getEntry("backboardMinimumOutputActive").setBoolean(backboardMinimumOutputActive); shooterNetworkTable.getEntry("backboardMinimumOutputActive").setBoolean(backboardMinimumOutputActive);
shooterNetworkTable.getEntry("backboardMaxOutputVolts").setDouble(Constants.Shooter.backboardSpeedMax); shooterNetworkTable.getEntry("backboardMaxOutputVolts").setDouble(Constants.Shooter.backboardSpeedMax);
shooterNetworkTable.getEntry("backboardMinOutputVolts").setDouble(Constants.Shooter.backboardSpeedMin); shooterNetworkTable.getEntry("backboardMinOutputVolts").setDouble(Constants.Shooter.backboardSpeedMin);
shooterNetworkTable.getEntry("backboardGravityFeedforwardMinVolts").setDouble(Constants.Shooter.backboardGravityFeedforwardMinVolts);
shooterNetworkTable.getEntry("backboardGravityFeedforwardMaxVolts").setDouble(Constants.Shooter.backboardGravityFeedforwardMaxVolts);
shooterNetworkTable.getEntry("backboardPositionTolerance").setDouble(10.0); shooterNetworkTable.getEntry("backboardPositionTolerance").setDouble(10.0);
shooterNetworkTable.getEntry("backboardShootPosition").setDouble(Constants.Superstructure.backboardShootPosition); shooterNetworkTable.getEntry("backboardShootPosition").setDouble(Constants.Superstructure.backboardShootPosition);
shooterNetworkTable.getEntry("backboardPassPosition").setDouble(Constants.Superstructure.passBallBackboardPosition); shooterNetworkTable.getEntry("backboardPassPosition").setDouble(Constants.Superstructure.passBallBackboardPosition);
@@ -230,14 +230,14 @@ public class Superstructure extends SubsystemBase {
intakeRotater.stop(); intakeRotater.stop();
shooter.stopFlywheel(); shooter.stopFlywheel();
shooter.stopShooterConveyor(); shooter.stopShooterConveyor();
shooter.holdBackboardAt(0.0); holdBackboardStowedUnlessTuning();
setSystemState(SystemState.STOWED); setSystemState(SystemState.STOWED);
} }
private void handleIntake() { private void handleIntake() {
shooter.stopFlywheel(); shooter.stopFlywheel();
shooter.stopShooterConveyor(); shooter.stopShooterConveyor();
shooter.holdBackboardAt(0.0); holdBackboardStowedUnlessTuning();
// Intaker 比赛开始后保持下放,收球何时结束由操作员松开按键决定。 // Intaker 比赛开始后保持下放,收球何时结束由操作员松开按键决定。
intakeRoller.intake(); intakeRoller.intake();
conveyor.feedToShooter(); conveyor.feedToShooter();
@@ -249,7 +249,7 @@ public class Superstructure extends SubsystemBase {
conveyor.stop(); conveyor.stop();
shooter.stopFlywheel(); shooter.stopFlywheel();
shooter.stopShooterConveyor(); shooter.stopShooterConveyor();
shooter.holdBackboardAt(0.0); holdBackboardStowedUnlessTuning();
setSystemState(SystemState.STOWED); setSystemState(SystemState.STOWED);
} }
@@ -309,8 +309,14 @@ public class Superstructure extends SubsystemBase {
conveyor.reverse(); conveyor.reverse();
shooter.runShooterConveyorVoltage(Constants.Superstructure.shooterReverseVoltage); shooter.runShooterConveyorVoltage(Constants.Superstructure.shooterReverseVoltage);
shooter.stopFlywheel(); shooter.stopFlywheel();
holdBackboardStowedUnlessTuning();
}
private void holdBackboardStowedUnlessTuning() {
if (!shooter.isBackboardPositionTuningActive()) {
shooter.holdBackboardAt(0.0); shooter.holdBackboardAt(0.0);
} }
}
private void handleManual() { private void handleManual() {
// 手动模式:状态机不再驱动机构,交给现场手动/调参工具; // 手动模式:状态机不再驱动机构,交给现场手动/调参工具;