Permalink
Find file
4abc49f Sep 13, 2016
794 lines (707 sloc) 29 KB
package com.team254.frc2016.subsystems;
import java.util.ArrayList;
import java.util.List;
import com.team254.frc2016.Constants;
import com.team254.frc2016.GoalTracker;
import com.team254.frc2016.RobotState;
import com.team254.frc2016.loops.Loop;
import com.team254.lib.util.InterpolatingDouble;
import com.team254.lib.util.Rotation2d;
import com.team254.lib.util.TimeDelayedBoolean;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.networktables.NetworkTable;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import static com.team254.frc2016.subsystems.Superstructure.WantedIntakeState.WANT_TO_RUN_INTAKE;
/**
* The overarching superclass containing all components of the superstructure:
* the computer vision, flywheel, hood, hood roller, and intake. This
* coordinates the entire firing sequence, from when the ball is intaked to when
* it is fired.
*
* @see Flywheel
* @see Hood
* @see HoodRoller
* @see Intake
* @see VisionServer
*/
public class Superstructure extends Subsystem {
static Superstructure mInstance = new Superstructure();
public static Superstructure getInstance() {
return mInstance;
}
/**
* Drives actual state, all outputs should be dictated by this state
*/
private enum SystemState {
REENABLED, // The shooter has just been enabled (and may have previously
// been disabled from any state)
DEPLOYED_AND_HOMING_HOOD, // The shooter is deployed and the hood is
// homing
STOWED_OR_STOWING, // The shooter is stowed (or stowing)
UNSTOWING, // The shooter is in the process of unstowing
LOADING, // The shooter is bringing in the ball
SPINNING_AIM, // The shooter is auto aiming
SPINNING_BATTER, // The shooter is in batter mode
FIRING_AIM, // The shooter is firing in auto aim mode
FIRING_BATTER, // The shooter is firing in batter mode
DEPLOYED, // The shooter is deployed but idle
KEEP_SPINNING, // The shooter is deployed and running but not aiming
DEPLOYED_RETURNING_TO_SAFE // The shooter is preparing to stow
}
/**
* Drives state changes. Outputs should not be decided based on this enum.
*/
public enum WantedState {
WANT_TO_DEPLOY, // The user is okay with leaving the hood up
WANT_TO_STOW, // The user wants to stow the shooter
WANT_TO_AIM, // The user wants to auto aim
WANT_TO_BATTER, // The user wants to use batter mode
WANT_TO_KEEP_SPINNING // The user wants to keep the wheel spinning
}
/**
* Orthogonal to the shooter state is the state of the firing mechanism.
* Outputs should not be decided based on this enum.
*/
public enum WantedFiringState {
WANT_TO_HOLD_FIRE, // The user does not wish to fire
WANT_TO_FIRE_NOW, // The user wants to fire now, regardless of readiness
WANT_TO_FIRE_WHEN_READY // The user wants to fire as soon as we achieve
// readiness
}
public enum WantedIntakeState {
WANT_TO_STOP_INTAKE, // The user does not wish to intake balls
WANT_TO_RUN_INTAKE, // The user wants to intake balls
WANT_TO_EXHAUST // The user wants to exhaust balls
}
private WantedState mWantedState = WantedState.WANT_TO_DEPLOY;
private WantedFiringState mWantedFiringState = WantedFiringState.WANT_TO_HOLD_FIRE;
private WantedIntakeState mWantedIntakeState = WantedIntakeState.WANT_TO_STOP_INTAKE;
private double mCurrentRangeForLogging;
private double mCurrentAngleForLogging;
private SystemState mSystemStateForLogging;
private boolean mTuningMode = false;
private double mTurretManualScanOutput = 0;
private ShooterAimingParameters mTurretManualSetpoint = null;
private double mHoodManualScanOutput = 0;
private double mHoodAdjustment = 0.0;
int mCurrentTrackId = -1;
int mConsecutiveCyclesOnTarget = 0;
int mNumShotsFired = 0;
private List<ShooterAimingParameters> mCachedAimingParams = new ArrayList<>();
Turret mTurret = new Turret();
Flywheel mFlywheel = new Flywheel();
Hood mHood = new Hood();
HoodRoller mHoodRoller = new HoodRoller();
Intake mIntake = new Intake();
RobotState mRobotState = RobotState.getInstance();
Drive mDrive = Drive.getInstance();
private final TimeDelayedBoolean mHasBallDelayedBoolean = new TimeDelayedBoolean();
NetworkTable mShooterTable = NetworkTable.getTable("shooter");
Loop mLoop = new Loop() {
private SystemState mSystemState = SystemState.REENABLED;
// Every time we transition states, we update the current state start
// time and the state changed boolean (for one cycle)
private double mCurrentStateStartTime;
private boolean mStateChanged;
@Override
public void onStart() {
synchronized (Superstructure.this) {
mHood.getLoop().onStart();
mHoodRoller.getLoop().onStart();
mWantedState = WantedState.WANT_TO_DEPLOY;
mWantedFiringState = WantedFiringState.WANT_TO_HOLD_FIRE;
mWantedIntakeState = WantedIntakeState.WANT_TO_STOP_INTAKE;
mCurrentStateStartTime = Timer.getFPGATimestamp();
mSystemState = SystemState.REENABLED;
mStateChanged = true;
mTurretManualSetpoint = null;
}
}
@Override
public void onLoop() {
synchronized (Superstructure.this) {
mHood.getLoop().onLoop();
double now = Timer.getFPGATimestamp();
SystemState newState;
switch (mSystemState) {
case REENABLED:
newState = handleReenabled();
break;
case DEPLOYED_AND_HOMING_HOOD:
newState = handleDeployedAndHomingHood();
break;
case STOWED_OR_STOWING:
newState = handleStowedOrStowing();
break;
case UNSTOWING:
newState = handleUnstowing(now, mCurrentStateStartTime);
break;
case LOADING:
newState = handleLoading(now, mCurrentStateStartTime);
break;
case SPINNING_AIM:
newState = handleSpinningAim(now, mStateChanged);
break;
case SPINNING_BATTER:
newState = handleSpinningBatter(now);
break;
case FIRING_AIM: // fallthrough
case FIRING_BATTER:
newState = handleShooting(mSystemState, now, mCurrentStateStartTime);
break;
case DEPLOYED:
newState = handleDeployed();
break;
case KEEP_SPINNING:
newState = handleKeepSpinning();
break;
case DEPLOYED_RETURNING_TO_SAFE:
newState = handleReturningToSafe(now, mCurrentStateStartTime);
break;
default:
System.out.println("Unexpected shooter state: " + mSystemState);
newState = SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
if (newState != mSystemState) {
System.out.println("Shooter state " + mSystemState + " to " + newState);
mSystemState = newState;
mCurrentStateStartTime = now;
mStateChanged = true;
} else {
mStateChanged = false;
}
mSystemStateForLogging = mSystemState;
mHoodRoller.getLoop().onLoop();
}
}
@Override
public void onStop() {
synchronized (Superstructure.this) {
mHood.getLoop().onStop();
mHoodRoller.getLoop().onStop();
mFlywheel.stop();
mHood.stop();
mTurret.stop();
mIntake.stop();
}
}
};
private Superstructure() {
}
public Loop getLoop() {
return mLoop;
}
public synchronized void setWantedState(WantedState newState) {
mWantedState = newState;
}
@Override
public void outputToSmartDashboard() {
mFlywheel.outputToSmartDashboard();
mHood.outputToSmartDashboard();
mTurret.outputToSmartDashboard();
mHoodRoller.outputToSmartDashboard();
mIntake.outputToSmartDashboard();
SmartDashboard.putNumber("current_range", mCurrentRangeForLogging);
SmartDashboard.putNumber("current_angle", mCurrentAngleForLogging);
SmartDashboard.putString("shooter_state", "" + mSystemStateForLogging);
}
@Override
public synchronized void stop() {
mFlywheel.stop();
mHood.stop();
mHoodRoller.stop();
mTurret.stop();
mIntake.stop();
}
@Override
public synchronized void zeroSensors() {
mFlywheel.zeroSensors();
mHood.zeroSensors();
mHoodRoller.zeroSensors();
mTurret.zeroSensors();
mCachedAimingParams.clear();
mIntake.zeroSensors();
}
public synchronized void resetTurretAtMax() {
mTurret.reset(Rotation2d.fromDegrees(Constants.kHardMaxTurretAngle));
}
public synchronized void resetTurretAtMin() {
mTurret.reset(Rotation2d.fromDegrees(Constants.kHardMinTurretAngle));
}
public synchronized void zeroTurret() {
mTurret.reset(new Rotation2d());
}
/**
* Sets the manual turret output ONLY when the turret is auto-aiming without
* a visible target
*/
public synchronized void setTurretManualScanOutput(double output) {
mTurretManualScanOutput = output;
}
public synchronized void setHoodManualScanOutput(double output) {
mHoodManualScanOutput = output;
}
public synchronized void setTurretManualPositionSetpoint(ShooterAimingParameters parameters) {
mTurretManualSetpoint = parameters;
}
public synchronized void clearTurretManualPositionSetpoint() {
mTurretManualSetpoint = null;
}
public void setTestServoSpeed(double speed) {
mHood.setTestServoSpeed(speed);
}
public synchronized void setWantsToFireNow() {
mWantedFiringState = WantedFiringState.WANT_TO_FIRE_NOW;
}
public synchronized void setWantsToFireWhenReady() {
mWantedFiringState = WantedFiringState.WANT_TO_FIRE_WHEN_READY;
}
public synchronized void setWantsToHoldFire() {
mWantedFiringState = WantedFiringState.WANT_TO_HOLD_FIRE;
}
public synchronized void setWantsToExhaust() {
mWantedIntakeState = WantedIntakeState.WANT_TO_EXHAUST;
}
public synchronized void setWantsToStopIntake() {
mWantedIntakeState = WantedIntakeState.WANT_TO_STOP_INTAKE;
}
public synchronized void setWantsToRunIntake() {
mWantedIntakeState = WANT_TO_RUN_INTAKE;
}
public synchronized void setHoodAdjustment(double adjustment) {
mHoodAdjustment = adjustment;
}
public synchronized void deployIntake() {
mIntake.setDeploy(true);
}
public synchronized void stowIntake() {
mIntake.setDeploy(false);
}
public synchronized int getNumShotsFired() {
return mNumShotsFired;
}
public Turret getTurret() {
return mTurret;
}
public Flywheel getFlywheel() {
return mFlywheel;
}
public Hood getHood() {
return mHood;
}
public synchronized void setTuningMode(boolean tuning_on) {
mTuningMode = tuning_on;
}
public Intake getIntake() {
return mIntake;
}
private synchronized SystemState handleReenabled() {
mCurrentTrackId = -1;
if (!mHood.hasHomed()) {
// We assume that this only happens when we are first enabled
return handleDeployedAndHomingHood();
}
mTurret.setDesiredAngle(new Rotation2d());
mHood.setStowed(false);
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
mHoodRoller.stop();
mFlywheel.stop();
if (mTurret.isSafe() && mHood.isSafe()) {
return handleDeployed();
} else {
double now = Timer.getFPGATimestamp();
return handleReturningToSafe(now, now);
}
}
private synchronized SystemState handleDeployedAndHomingHood() {
mCurrentTrackId = -1;
handleIntake(false, false);
mTurret.setDesiredAngle(new Rotation2d());
mFlywheel.stop();
mHood.setStowed(false);
mHoodRoller.stop();
return mHood.hasHomed() ? SystemState.DEPLOYED : SystemState.DEPLOYED_AND_HOMING_HOOD;
}
private synchronized SystemState handleStowedOrStowing() {
mCurrentTrackId = -1;
handleIntake(false, false);
mTurret.setDesiredAngle(new Rotation2d());
mFlywheel.stop();
mHood.setStowed(true);
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
if (mWantedIntakeState == WantedIntakeState.WANT_TO_EXHAUST) {
mHoodRoller.reverse();
} else {
mHoodRoller.stop();
}
switch (mWantedState) {
case WANT_TO_AIM: // fallthrough
case WANT_TO_BATTER:
case WANT_TO_DEPLOY:
case WANT_TO_KEEP_SPINNING:
return SystemState.UNSTOWING;
case WANT_TO_STOW: // fallthrough
default:
// Nothing to do, these outputs are redundant
return SystemState.STOWED_OR_STOWING;
}
}
private synchronized SystemState handleUnstowing(double now, double stateStartTime) {
mCurrentTrackId = -1;
handleIntake(true, false);
mTurret.setDesiredAngle(new Rotation2d());
mFlywheel.stop();
mHood.setStowed(false);
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
mHoodRoller.stop();
mRobotState.resetVision();
// State transitions
boolean isDoneUnstowing = now - stateStartTime > Constants.kHoodUnstowToFlywheelSpinTime;
switch (mWantedState) {
case WANT_TO_DEPLOY:
if (!isDoneUnstowing) {
return SystemState.UNSTOWING;
} else {
return SystemState.DEPLOYED;
}
case WANT_TO_KEEP_SPINNING:
if (!isDoneUnstowing) {
return SystemState.UNSTOWING;
} else {
return SystemState.KEEP_SPINNING;
}
case WANT_TO_AIM:
case WANT_TO_BATTER: // fallthrough
if (!isDoneUnstowing) {
return SystemState.UNSTOWING;
} else {
return SystemState.LOADING;
}
case WANT_TO_STOW: // fallthrough
default:
mHood.startHoming();
return SystemState.STOWED_OR_STOWING;
}
}
private synchronized SystemState handleLoading(double now, double stateStartTime) {
mCurrentTrackId = -1;
handleIntake(true, true);
mTurret.setDesiredAngle(new Rotation2d());
mFlywheel.setRpm(Constants.kFlywheelGoodBallRpmSetpoint);
mHood.setStowed(false);
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
mHoodRoller.intake();
switch (mWantedState) {
case WANT_TO_AIM: // fallthrough
case WANT_TO_BATTER:
case WANT_TO_DEPLOY:
case WANT_TO_KEEP_SPINNING:
boolean isDoneLoading = now - stateStartTime > Constants.kLoadingTime;
if (isDoneLoading || mHoodRoller.isBallPresent()) {
mRobotState.resetVision();
mCurrentTrackId = -1;
if (mWantedState == WantedState.WANT_TO_AIM) {
return SystemState.SPINNING_AIM;
} else if (mWantedState == WantedState.WANT_TO_BATTER) {
return SystemState.SPINNING_BATTER;
} else if (mWantedState == WantedState.WANT_TO_KEEP_SPINNING) {
return SystemState.KEEP_SPINNING;
} else {
return SystemState.DEPLOYED;
}
} else {
return SystemState.LOADING;
}
case WANT_TO_STOW:
default:
return SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
}
private synchronized SystemState handleSpinningAim(double now, boolean isFirstCycle) {
handleIntake(true, false);
if (isFirstCycle) {
// Start flywheel
mFlywheel.setRpm(Constants.kFlywheelGoodBallRpmSetpoint);
mConsecutiveCyclesOnTarget = 0;
}
mHood.setStowed(false);
mHoodRoller.intake();
autoAim(now, true);
// State transition
switch (mWantedState) {
case WANT_TO_AIM:
if (mWantedFiringState == WantedFiringState.WANT_TO_FIRE_NOW
|| (mWantedFiringState == WantedFiringState.WANT_TO_FIRE_WHEN_READY
&& readyToFire(SystemState.SPINNING_AIM, now))) {
System.out.println("FIRING BALL " + (mNumShotsFired + 1) + "\nAngle to Goal: " + mCurrentAngleForLogging
+ ", Distance to Goal: " + mCurrentRangeForLogging + "\nHood Angle (desired): "
+ mHood.getSetpoint() + ", (actual): " + mHood.getAngle() + ", adjustment: " + mHoodAdjustment
+ "\nTurret Angle (desired): " + mTurret.getSetpoint() + ", (actual): " + mTurret.getAngle()
+ "\nFlywheel RPM (desired): " + mFlywheel.getSetpoint() + ", (actual): " + mFlywheel.getRpm());
return SystemState.FIRING_AIM;
} else {
return SystemState.SPINNING_AIM;
}
case WANT_TO_BATTER:
return SystemState.SPINNING_BATTER;
case WANT_TO_DEPLOY:
return SystemState.DEPLOYED;
case WANT_TO_KEEP_SPINNING:
return SystemState.KEEP_SPINNING;
case WANT_TO_STOW: // fallthrough
default:
return SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
}
private synchronized SystemState handleSpinningBatter(double now) {
handleIntake(true, false);
mTurret.setDesiredAngle(new Rotation2d());
mFlywheel.setRpm(Constants.kFlywheelGoodBallRpmSetpoint);
mHood.setStowed(false);
mHoodRoller.intake();
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
// state transitions
switch (mWantedState) {
case WANT_TO_AIM:
return SystemState.SPINNING_AIM;
case WANT_TO_BATTER:
if (mWantedFiringState == WantedFiringState.WANT_TO_FIRE_NOW
|| (mWantedFiringState == WantedFiringState.WANT_TO_FIRE_WHEN_READY
&& readyToFire(SystemState.SPINNING_BATTER, now))) {
return SystemState.FIRING_BATTER;
} else {
return SystemState.SPINNING_BATTER;
}
case WANT_TO_DEPLOY:
return SystemState.DEPLOYED;
case WANT_TO_KEEP_SPINNING:
return SystemState.KEEP_SPINNING;
case WANT_TO_STOW: // fallthrough
default:
return SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
}
private synchronized SystemState handleShooting(SystemState state, double now, double stateStartTime) {
handleIntake(true, true);
if (state == SystemState.FIRING_AIM) {
autoAim(now, true);
}
if (now - stateStartTime < Constants.kShootActuationTime) {
mHoodRoller.shoot();
return state;
} else {
mHoodRoller.stop();
mNumShotsFired++;
mRobotState.resetVision();
mCurrentTrackId = -1;
switch (mWantedState) {
case WANT_TO_AIM:
return SystemState.SPINNING_AIM;
case WANT_TO_BATTER:
return SystemState.SPINNING_BATTER;
case WANT_TO_DEPLOY:
return SystemState.DEPLOYED;
case WANT_TO_KEEP_SPINNING:
return SystemState.KEEP_SPINNING;
case WANT_TO_STOW: // fallthrough
default:
return SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
}
}
private synchronized SystemState handleDeployed() {
mCurrentTrackId = -1;
mTurret.setDesiredAngle(new Rotation2d());
handleIntake(!mTurret.isSafe(), false);
mFlywheel.stop();
mHood.setStowed(false);
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
if (mWantedIntakeState == WantedIntakeState.WANT_TO_EXHAUST) {
mHoodRoller.reverse();
} else {
mHoodRoller.stop();
}
switch (mWantedState) {
case WANT_TO_AIM: // fallthrough
case WANT_TO_BATTER:
return SystemState.LOADING;
case WANT_TO_DEPLOY:
return SystemState.DEPLOYED;
case WANT_TO_KEEP_SPINNING:
return SystemState.KEEP_SPINNING;
case WANT_TO_STOW: // fallthrough
default:
return SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
}
private synchronized SystemState handleKeepSpinning() {
mCurrentTrackId = -1;
mTurret.setDesiredAngle(new Rotation2d());
handleIntake(!mTurret.isSafe(), false);
mFlywheel.setRpm(Constants.kFlywheelGoodBallRpmSetpoint);
mHood.setStowed(false);
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
if (mWantedIntakeState == WantedIntakeState.WANT_TO_EXHAUST) {
mHoodRoller.reverse();
} else {
mHoodRoller.stop();
}
switch (mWantedState) {
case WANT_TO_AIM: // fallthrough
case WANT_TO_BATTER:
return SystemState.LOADING;
case WANT_TO_DEPLOY:
return SystemState.DEPLOYED;
case WANT_TO_KEEP_SPINNING:
return SystemState.KEEP_SPINNING;
case WANT_TO_STOW: // fallthrough
default:
return SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
}
private synchronized SystemState handleReturningToSafe(double now, double start_time) {
mCurrentTrackId = -1;
handleIntake(true, false);
mTurret.setDesiredAngle(new Rotation2d());
mFlywheel.stop();
mHood.setStowed(false);
mHoodRoller.stop();
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kBatterHoodAngle));
switch (mWantedState) {
case WANT_TO_AIM:
return SystemState.SPINNING_AIM;
case WANT_TO_BATTER:
return SystemState.SPINNING_BATTER;
case WANT_TO_DEPLOY:
return SystemState.DEPLOYED;
case WANT_TO_KEEP_SPINNING:
return SystemState.KEEP_SPINNING;
default:
if ((mTurret.isSafe() && mHood.isSafe()) || (now - start_time > Constants.kStowingOverrideTime)) {
mHood.startHoming();
return SystemState.STOWED_OR_STOWING;
} else {
return SystemState.DEPLOYED_RETURNING_TO_SAFE;
}
}
}
private double getHoodAngleForRange(double range) {
InterpolatingDouble result = Constants.kHoodAutoAimMap.getInterpolated(new InterpolatingDouble(range));
if (result != null) {
return result.value;
} else {
return Constants.kHoodNeutralAngle;
}
}
private List<ShooterAimingParameters> getCurrentAimingParameters(double now) {
List<ShooterAimingParameters> params = mRobotState.getAimingParameters(now,
new GoalTracker.TrackReportComparator(Constants.kTrackReportComparatorStablityWeight,
Constants.kTrackReportComparatorAgeWeight, Constants.kTrackReportComparatorSwitchingWeight,
mCurrentTrackId, now));
mCachedAimingParams = params;
return params;
}
public List<ShooterAimingParameters> getCachedAimingParams() {
return mCachedAimingParams;
}
private void autoAim(double now, boolean allow_changing_tracks) {
List<ShooterAimingParameters> aimingParameters = getCurrentAimingParameters(now);
if (aimingParameters.isEmpty() && (allow_changing_tracks || mTurretManualSetpoint != null)) {
// Manual search
if (mTurretManualSetpoint != null) {
mTurret.setDesiredAngle(mTurretManualSetpoint.getTurretAngle());
mHood.setDesiredAngle(Rotation2d.fromDegrees(getHoodAngleForRange(mTurretManualSetpoint.range)));
} else {
mTurret.setOpenLoop(mTurretManualScanOutput);
if (!mTuningMode) {
mHood.setDesiredAngle(Rotation2d.fromDegrees(Constants.kHoodNeutralAngle));
} else {
mHood.setOpenLoop(mHoodManualScanOutput);
}
}
mFlywheel.setRpm(Constants.kFlywheelGoodBallRpmSetpoint);
} else {
// Pick the target to aim at
boolean has_target = false;
for (ShooterAimingParameters param : aimingParameters) {
double turret_angle_degrees = param.getTurretAngle().getDegrees();
if (turret_angle_degrees >= Constants.kSoftMinTurretAngle
&& turret_angle_degrees <= Constants.kSoftMaxTurretAngle
&& param.getRange() >= Constants.kAutoAimMinRange
&& param.getRange() <= Constants.kAutoAimMaxRange
&& (allow_changing_tracks || mCurrentTrackId == param.getTrackid())) {
// This target works
mFlywheel.setRpm(getShootingSetpointRpm(param.getRange()));
if (!mTuningMode) {
double angle_degrees = getHoodAngleForRange(param.getRange()) + mHoodAdjustment;
angle_degrees = Math.max(angle_degrees, Constants.kMinHoodAngle);
angle_degrees = Math.min(angle_degrees, Constants.kMaxHoodAngle);
mHood.setDesiredAngle(Rotation2d.fromDegrees(angle_degrees));
} else {
mHood.setOpenLoop(mHoodManualScanOutput);
}
mTurret.setDesiredAngle(param.getTurretAngle());
mCurrentAngleForLogging = param.getTurretAngle().getDegrees();
mCurrentRangeForLogging = param.getRange();
mCurrentTrackId = param.getTrackid();
has_target = true;
break;
}
}
if (!has_target) {
mCurrentTrackId = -1;
}
}
}
public synchronized boolean HasTarget() {
return mCurrentTrackId != -1;
}
private double getShootingSetpointRpm(double range) {
return Constants.kFlywheelAutoAimMap.getInterpolated(new InterpolatingDouble(range)).value;
}
private boolean readyToFire(SystemState state, double now) {
boolean is_stopped = Math.abs(mDrive.getLeftVelocityInchesPerSec()) < Constants.kAutoShootMaxDriveSpeed
&& Math.abs(mDrive.getRightVelocityInchesPerSec()) < Constants.kAutoShootMaxDriveSpeed;
if (state == SystemState.SPINNING_AIM) {
if ((mTuningMode || mHood.isOnTarget()) && mFlywheel.isOnTarget() && mTurret.isOnTarget()
&& (mCurrentTrackId != -1)) {
mConsecutiveCyclesOnTarget++;
} else {
mConsecutiveCyclesOnTarget = 0;
}
} else if (state == SystemState.SPINNING_BATTER) {
if ((mTuningMode || mHood.isOnTarget()) && mFlywheel.isOnTarget() && mTurret.isOnTarget()) {
mConsecutiveCyclesOnTarget++;
} else {
mConsecutiveCyclesOnTarget = 0;
}
} else {
mConsecutiveCyclesOnTarget = 0;
}
return mConsecutiveCyclesOnTarget > Constants.kAutoAimMinConsecutiveCyclesOnTarget && is_stopped;
}
private void handleIntake(boolean disallow_intaking, boolean loading) {
boolean hasBallDelayed = false;
if (mWantedIntakeState == WANT_TO_RUN_INTAKE && !disallow_intaking) {
hasBallDelayed = mHasBallDelayedBoolean.update(mIntake.hasBall(), 0.125);
} else {
mHasBallDelayedBoolean.update(false, 0);
}
switch (mWantedIntakeState) {
case WANT_TO_RUN_INTAKE:
if (disallow_intaking) {
mIntake.setIntakeRoller(0.0, loading ? 1.0 : 0.0);
} else {
mIntake.setIntakeRoller(1.0, hasBallDelayed ? 0.0 : 1.0);
}
break;
case WANT_TO_EXHAUST:
mIntake.setIntakeRoller(-1.0, loading ? 1.0 : -1.0);
break;
case WANT_TO_STOP_INTAKE:
default:
mIntake.setIntakeRoller(0.0, loading ? 1.0 : 0.0);
break;
}
}
}