From bd6faf25a2806ba19d3bc9f72c9dfd50da7d640c Mon Sep 17 00:00:00 2001 From: AvidhBavkar Date: Sat, 10 Mar 2018 04:40:05 -0800 Subject: [PATCH] Arizona Day 1: End of Day. all subsystems operational --- .../frc2018/commands/RunIntakeWheels.class | Bin 732 -> 714 bytes dist/FRCUserProgram.jar | Bin 670077 -> 712053 bytes src/com/team3925/frc2018/OI.java | 371 ++++++++++------- src/com/team3925/frc2018/Robot.java | 163 +++++--- src/com/team3925/frc2018/RobotMap.java | 102 ++--- .../frc2018/commands/SetLiftBottom.java | 46 --- .../team3925/frc2018/commands/SetLiftTop.java | 20 - .../team3925/frc2018/commands/ShootCube.java | 55 +-- .../team3925/frc2018/commands/ZeroIntake.java | 66 +-- .../commands/autos/CenterLeftSwitchAuto.java | 25 -- ...tSwitchAuto.java => CenterSwitchAuto.java} | 60 +-- .../commands/autos/DriveForwardAuto.java | 15 + .../frc2018/subsystems/Drivetrain.java | 355 ++++++++--------- .../team3925/frc2018/subsystems/Elevator.java | 265 ++++++------ .../team3925/frc2018/subsystems/Intake.java | 230 +++++------ src/com/team3925/utils/GnarlyController.java | 376 +++++++++--------- 16 files changed, 1106 insertions(+), 1043 deletions(-) delete mode 100644 src/com/team3925/frc2018/commands/SetLiftBottom.java delete mode 100644 src/com/team3925/frc2018/commands/SetLiftTop.java delete mode 100644 src/com/team3925/frc2018/commands/autos/CenterLeftSwitchAuto.java rename src/com/team3925/frc2018/commands/autos/{CenterRightSwitchAuto.java => CenterSwitchAuto.java} (55%) create mode 100644 src/com/team3925/frc2018/commands/autos/DriveForwardAuto.java diff --git a/build/com/team3925/frc2018/commands/RunIntakeWheels.class b/build/com/team3925/frc2018/commands/RunIntakeWheels.class index 20edb0c12cf18a035be43f7c84da0bca5f87a8f6..c3730b6b7844d57514d4287faabe5863c4160416 100644 GIT binary patch delta 347 zcmYk0J5B>Z5Jcb1{@C$iu)#Ke;|Q~INMZ>&vN!@Kz=0ElgcBmpu(u!}LE+!loP?fZi){}(8M_&KhUEHcHoGvGsUba` zU(Od3Lp+>Tqnl`Wd|us+J2|a_jFpW2f&=;mhq&tNdF^PdGv&R5VI7*X4n+Otjf_8LRUMf#nx1P=Tr3$>$K|3akv4E*9B4eh9s00Ox@m%m4rY delta 367 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�VoyA0WmVrBND$R$c+i&>r6Dz3av5zG5W$yD`t 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

E0#vwr{aF`=zLm;nuamlGZnYQKNpH2ylFVa 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 diff --git a/src/com/team3925/frc2018/OI.java b/src/com/team3925/frc2018/OI.java index c393130..6437d94 100644 --- a/src/com/team3925/frc2018/OI.java +++ b/src/com/team3925/frc2018/OI.java @@ -1,149 +1,222 @@ -package com.team3925.frc2018; - -import com.team3925.frc2018.commands.CloseGrabbers; -import com.team3925.frc2018.commands.DecrementAdjustElevator; -import com.team3925.frc2018.commands.DriveManual.DriveManualInput; -import com.team3925.frc2018.commands.DropCube; -import com.team3925.frc2018.commands.IncrementAdjustElevator; -import com.team3925.frc2018.commands.OpenGrabbers; -import com.team3925.frc2018.commands.RunElevator; -import com.team3925.frc2018.commands.RunIntakeWheels; -import com.team3925.frc2018.commands.SetLiftBottom; -import com.team3925.frc2018.commands.SetLiftTop; -import com.team3925.frc2018.commands.ShiftHigh; -import com.team3925.frc2018.commands.ShiftLow; -import com.team3925.frc2018.commands.ShootCube; -import com.team3925.frc2018.subsystems.Elevator.ElevatorState; - -import edu.wpi.first.wpilibj.Joystick; -import edu.wpi.first.wpilibj.buttons.Button; -import edu.wpi.first.wpilibj.buttons.JoystickButton; -import edu.wpi.first.wpilibj.buttons.Trigger; - -public class OI implements DriveManualInput{ - - private final Joystick wheel; - private final Joystick xbox; - private final Joystick stick; - - private static OI instance; - - private Button drivetrain_Shift; - - private Button jogElevatorTop; - private Button jogElevatorScaleHigh; - private Button jogElevatorScaleMiddle; - private Button jogElevatorScaleLow; - private Button jogElevatorSwitch; - private Button jogElevatorBottom; - private Trigger dropCube; - private Trigger shootCube; - private Button intakeCube; - private Button openIntake; - - private Trigger tuneUp; - private Trigger tuneDown; - - public static OI getInstance() { - if (instance == null) - instance = new OI(); - return instance; - } - - private OI() { - stick = new Joystick(0); - wheel = new Joystick(1); - xbox = new Joystick(2); - - jogElevatorTop = new JoystickButton(xbox, 9); - jogElevatorScaleHigh = new JoystickButton(xbox, 4); - jogElevatorScaleMiddle = new JoystickButton(xbox, 2); - jogElevatorScaleLow = new JoystickButton(xbox, 1); - jogElevatorSwitch = new JoystickButton(xbox, 3); - jogElevatorBottom = new JoystickButton(xbox, 10); - - drivetrain_Shift = new JoystickButton(wheel, 5); - - openIntake = new JoystickButton(xbox, 5); - intakeCube = new JoystickButton(xbox, 6); - - dropCube = new Trigger() { - @Override - public boolean get() { - return xbox.getPOV() == 180; - } - }; - - shootCube = new Trigger() { - - @Override - public boolean get() { - return xbox.getPOV() == 0; - } - }; - - tuneUp = new Trigger() { - - @Override - public boolean get() { - return xbox.getRawAxis(3) > 0.7; - } - }; - - tuneDown = new Trigger() { - @Override - public boolean get() { - return xbox.getRawAxis(2) > 0.7; - } - }; - - - jogElevatorTop.whenPressed(new RunElevator(ElevatorState.TOP)); - jogElevatorScaleHigh.whenPressed(new RunElevator(ElevatorState.SCALE_MAX)); - jogElevatorScaleMiddle.whenPressed(new RunElevator(ElevatorState.SCALE_MED)); - jogElevatorScaleLow.whenPressed(new RunElevator(ElevatorState.SCALE_LOW)); - jogElevatorSwitch.whenPressed(new RunElevator(ElevatorState.SWITCH)); - jogElevatorBottom.whenPressed(new RunElevator(ElevatorState.BOTTOM)); - - dropCube.whenActive(new DropCube()); - shootCube.whenActive(new ShootCube()); - - drivetrain_Shift.whenPressed(new ShiftLow()); - drivetrain_Shift.whenReleased(new ShiftHigh()); - - openIntake.whenPressed(new OpenGrabbers()); - openIntake.whenReleased(new CloseGrabbers()); - - intakeCube.whenPressed(new RunIntakeWheels(1)); - intakeCube.whenPressed(new SetLiftBottom()); - intakeCube.whenReleased(new RunIntakeWheels(0)); - intakeCube.whenReleased(new SetLiftTop()); - - tuneUp.whenActive(new IncrementAdjustElevator()); - tuneDown.whenActive(new DecrementAdjustElevator()); - } - - @Override - public double getLeft() { - return wheel.getRawAxis(0); - } - - @Override public double getFwd() { - return -stick.getRawAxis(1); - } - - public double getElevator() { - return -xbox.getRawAxis(1); - } - - public double getLiftIntake() { - return stick.getRawAxis(2); - } - - public double getRawElevator() { - return xbox.getRawAxis(5); - } - public boolean getTestButton() { - return wheel.getRawButton(4); - } -} +package com.team3925.frc2018; + +import com.team3925.frc2018.commands.CloseGrabbers; +import com.team3925.frc2018.commands.DecrementAdjustElevator; +import com.team3925.frc2018.commands.DriveManual.DriveManualInput; +import com.team3925.frc2018.commands.DropCube; +import com.team3925.frc2018.commands.IncrementAdjustElevator; +import com.team3925.frc2018.commands.OpenGrabbers; +import com.team3925.frc2018.commands.RunElevator; +import com.team3925.frc2018.commands.RunIntakeWheels; +import com.team3925.frc2018.commands.ShiftHigh; +import com.team3925.frc2018.commands.ShiftLow; +import com.team3925.frc2018.subsystems.Elevator; +import com.team3925.frc2018.subsystems.Elevator.ElevatorState; +import com.team3925.frc2018.subsystems.Intake; + +import edu.wpi.first.wpilibj.Joystick; +import edu.wpi.first.wpilibj.buttons.Button; +import edu.wpi.first.wpilibj.buttons.JoystickButton; +import edu.wpi.first.wpilibj.buttons.Trigger; +import edu.wpi.first.wpilibj.command.Command; + +public class OI implements DriveManualInput { + + private final Joystick wheel; + private final Joystick xbox; + private final Joystick stick; + + private static OI instance; + + private Button drivetrain_Shift; + + private Button jogElevatorTop; + private Button jogElevatorScaleHigh; + private Button jogElevatorScaleMiddle; + private Button jogElevatorScaleLow; + private Button jogElevatorSwitch; + private Button jogElevatorBottom; + private Trigger dropCube; + private Trigger shootCube; + private Button intakeCube; + private Button openIntake; + + private Trigger tuneUp; + private Trigger tuneDown; + + public static OI getInstance() { + if (instance == null) + instance = new OI(); + return instance; + } + + private OI() { + stick = new Joystick(0); + wheel = new Joystick(1); + xbox = new Joystick(2); + + jogElevatorTop = new JoystickButton(xbox, 9); + jogElevatorScaleHigh = new JoystickButton(xbox, 4); + jogElevatorScaleMiddle = new JoystickButton(xbox, 2); + jogElevatorScaleLow = new JoystickButton(xbox, 1); + jogElevatorSwitch = new JoystickButton(xbox, 3); + jogElevatorBottom = new JoystickButton(xbox, 10); + + drivetrain_Shift = new JoystickButton(wheel, 5); + + openIntake = new JoystickButton(xbox, 5); + intakeCube = new JoystickButton(xbox, 6); + + dropCube = new Trigger() { + @Override + public boolean get() { + return xbox.getPOV() == 180; + } + }; + + shootCube = new Trigger() { + + @Override + public boolean get() { + return xbox.getPOV() == 0; + } + }; + + tuneUp = new Trigger() { + + @Override + public boolean get() { + return xbox.getRawAxis(3) > 0.7; + } + }; + + tuneDown = new Trigger() { + @Override + public boolean get() { + return xbox.getRawAxis(2) > 0.7; + } + }; + + Trigger zeroElevator = new Trigger() { + + @Override + public boolean get() { + return Elevator.getInstance().getLimitSwitch(); + } + }; + + zeroElevator.whenActive(new Command (){ + + @Override + protected void initialize() { + Elevator.getInstance().zero(); + } + + @Override + protected boolean isFinished() { + return true; + } + }); + + jogElevatorTop.whenPressed(new RunElevator(ElevatorState.TOP)); + jogElevatorScaleHigh.whenPressed(new RunElevator(ElevatorState.SCALE_MAX)); + jogElevatorScaleMiddle.whenPressed(new RunElevator(ElevatorState.SCALE_MED)); + jogElevatorScaleLow.whenPressed(new RunElevator(ElevatorState.SCALE_LOW)); + jogElevatorSwitch.whenPressed(new RunElevator(ElevatorState.SWITCH)); + jogElevatorBottom.whenPressed(new RunElevator(ElevatorState.BOTTOM)); + + dropCube.whenActive(new DropCube()); + shootCube.whileActive(new Command() { + @Override + protected void initialize() { + Intake.getInstance().setAngle(0); + } + @Override + protected void execute() { + } + + @Override + protected void end() { + Intake.getInstance().setIntakeRollers(-1); + } + + @Override + protected boolean isFinished() { + return Intake.getInstance().isAtSetpoint(); + } + }); + shootCube.whenInactive(new Command() { + + @Override + protected void initialize() { + Intake.getInstance().setIntakeRollers(0); + Intake.getInstance().setAngle(85); + } + @Override + protected boolean isFinished() { + return true; + } + }); + + drivetrain_Shift.whenPressed(new ShiftLow()); + drivetrain_Shift.whenReleased(new ShiftHigh()); + + openIntake.whenPressed(new OpenGrabbers()); + openIntake.whenReleased(new CloseGrabbers()); + + intakeCube.whenPressed(new RunIntakeWheels(1)); + intakeCube.whenPressed(new Command() { + + @Override + protected void initialize() { + Intake.getInstance().setAngle(0); + } + @Override + protected boolean isFinished() { + return true; + } + }); + intakeCube.whenReleased(new RunIntakeWheels(0)); + intakeCube.whenInactive(new Command() { + + @Override + protected void initialize() { + Intake.getInstance().setAngle(85); + } + + @Override + protected boolean isFinished() { + return true; + } + }); + + tuneUp.whenActive(new IncrementAdjustElevator()); + tuneDown.whenActive(new DecrementAdjustElevator()); + } + + @Override + public double getLeft() { + return wheel.getRawAxis(0); + } + + @Override + public double getFwd() { + return -stick.getRawAxis(1); + } + + public double getElevator() { + return -xbox.getRawAxis(1); + } + + public double getLiftIntake() { + return stick.getRawAxis(2); + } + + public double getRawElevator() { + return xbox.getRawAxis(5); + } + + public boolean getTestButton() { + return wheel.getRawButton(4); + } +} diff --git a/src/com/team3925/frc2018/Robot.java b/src/com/team3925/frc2018/Robot.java index 20e670f..cb005e3 100644 --- a/src/com/team3925/frc2018/Robot.java +++ b/src/com/team3925/frc2018/Robot.java @@ -1,60 +1,103 @@ -package com.team3925.frc2018; - -import com.team3925.frc2018.commands.DriveManual; -import com.team3925.frc2018.commands.RunElevator; -import com.team3925.frc2018.commands.RunElevatorRaw; -import com.team3925.frc2018.commands.RunIntakeLiftRaw; -import com.team3925.frc2018.commands.ZeroIntake; -import com.team3925.frc2018.subsystems.Elevator; -import com.team3925.frc2018.subsystems.Intake; - -import edu.wpi.first.wpilibj.IterativeRobot; -import edu.wpi.first.wpilibj.command.Command; -import edu.wpi.first.wpilibj.command.Scheduler; - -public class Robot extends IterativeRobot { - DriveManual drive; - RunElevator elevate; - RunElevatorRaw elevateRaw; - RunIntakeLiftRaw liftRaw; - Command testAuto; - Command zeroIntake; - - @Override - public void robotInit() { - drive = new DriveManual(OI.getInstance()); - elevateRaw = new RunElevatorRaw(); - liftRaw = new RunIntakeLiftRaw(); - zeroIntake = new ZeroIntake(); - } - - @Override - public void autonomousInit() { -// Elevator.getInstance().zero(); -// -// if (DriverStation.getInstance().getGameSpecificMessage().charAt(0) == 'L') { -// testAuto = new CenterLeftSwitchAuto(); -// }else if(DriverStation.getInstance().getGameSpecificMessage().charAt(0) == 'R') { -// testAuto = new CenterRightSwitchAuto(); -// } -// testAuto.start(); - } - - public void teleopInit() { - Elevator.getInstance().zero(); - drive.start(); - Intake.getInstance().setIntakeRollers(-0.1); - zeroIntake.start(); - } - - @Override - public void teleopPeriodic() { - - } - - @Override - public void robotPeriodic() { - Logger.getInstance().update(); - Scheduler.getInstance().run(); - } -} +package com.team3925.frc2018; + +import com.team3925.frc2018.commands.DriveManual; +import com.team3925.frc2018.commands.RunElevator; +import com.team3925.frc2018.commands.RunElevatorRaw; +import com.team3925.frc2018.commands.RunIntakeLiftRaw; +import com.team3925.frc2018.commands.ZeroIntake; +import com.team3925.frc2018.commands.autos.CenterSwitchAuto; +import com.team3925.frc2018.commands.autos.CenterSwitchAuto.AutoSide; +import com.team3925.frc2018.commands.autos.DriveForwardAuto; +import com.team3925.frc2018.subsystems.Drivetrain; +import com.team3925.frc2018.subsystems.Elevator; +import com.team3925.frc2018.subsystems.Intake; +import com.team3925.frc2018.subsystems.Elevator.ElevatorState; + +import edu.wpi.cscore.UsbCamera; +import edu.wpi.first.wpilibj.CameraServer; +import edu.wpi.first.wpilibj.DriverStation; +import edu.wpi.first.wpilibj.IterativeRobot; +import edu.wpi.first.wpilibj.command.Command; +import edu.wpi.first.wpilibj.command.Scheduler; +import edu.wpi.first.wpilibj.smartdashboard.SendableChooser; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; + +public class Robot extends IterativeRobot { + DriveManual drive; + RunElevator elevate; + RunElevatorRaw elevateRaw; + RunIntakeLiftRaw liftRaw; + Command testAuto; + Command zeroIntake; + UsbCamera camera; + SendableChooser autoSelector; + boolean isElevatorZeroed = false; + + @Override + public void robotInit() { + autoSelector = new SendableChooser(); + drive = new DriveManual(OI.getInstance()); + elevateRaw = new RunElevatorRaw(); + liftRaw = new RunIntakeLiftRaw(); + zeroIntake = new ZeroIntake(); + camera = CameraServer.getInstance().startAutomaticCapture(); + camera.setResolution(320, 240); + camera.setFPS(12); + autoSelector.addDefault("Drive Forward", "DriveForward"); + autoSelector.addObject("CenterSwitch", "Center"); + SmartDashboard.putData("Auto", autoSelector); + isElevatorZeroed = false; + } + + @Override + public void autonomousInit() { + isElevatorZeroed = true; + Elevator.getInstance().zero(); + Intake.getInstance().zeroLift(); + testAuto = new DriveForwardAuto(); + if (autoSelector.getSelected().equals("DriveForward")) { + testAuto = new DriveForwardAuto(); + }else if(autoSelector.getSelected().equals("Center")){ + if (DriverStation.getInstance().getGameSpecificMessage().charAt(0) == 'L') { + testAuto = new CenterSwitchAuto(AutoSide.LEFT); + System.out.println("RUNnningLEFt"); + }else if(DriverStation.getInstance().getGameSpecificMessage().charAt(0) == 'R') { + testAuto = new CenterSwitchAuto(AutoSide.RIGHT); + } + } + testAuto.start(); + } + + @Override + public void autonomousPeriodic() { + } + + public void teleopInit() { + if (!isElevatorZeroed) { + Elevator.getInstance().zero(); + Intake.getInstance().zeroLift(); + } + drive.start(); + Intake.getInstance().setIntakeRollers(0.3); +// Elevator.getInstance().setPosition(ElevatorState.BOTTOM); +// Intake.getInstance().zeroLift(); + } + + @Override + public void teleopPeriodic() { + if (Elevator.getInstance().getLimitSwitch()) { + Elevator.getInstance().zero(); + } + } + + @Override + public void robotPeriodic() { + Logger.getInstance().update(); + Scheduler.getInstance().run(); + } + + @Override + public void disabledInit() { + isElevatorZeroed = false; + } +} diff --git a/src/com/team3925/frc2018/RobotMap.java b/src/com/team3925/frc2018/RobotMap.java index 4b0c699..13f78a0 100644 --- a/src/com/team3925/frc2018/RobotMap.java +++ b/src/com/team3925/frc2018/RobotMap.java @@ -1,51 +1,51 @@ -package com.team3925.frc2018; - -import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX; -import com.ctre.phoenix.motorcontrol.can.WPI_VictorSPX; -import com.ctre.phoenix.sensors.PigeonIMU; -import com.team3925.utils.CTREControllerFactory; - -import edu.wpi.first.wpilibj.DoubleSolenoid; - -public class RobotMap { - - public static final class DrivetrainMap { - public static final WPI_TalonSRX LEFT_MASTER = CTREControllerFactory.createDefaultTalon(4); -// public static final WPI_TalonSRX LEFT_SLAVE_A = CTREControllerFactory.createDefaultTalon(5); - public static final WPI_TalonSRX LEFT_SLAVE_A = CTREControllerFactory.createPermanentSlaveTalon(5, LEFT_MASTER); -// public static final WPI_VictorSPX LEFT_SLAVE_B = CTREControllerFactory.createDefaultVictor(6); - public static final WPI_VictorSPX LEFT_SLAVE_B = CTREControllerFactory.createPermanentSlaveVictor(6, - LEFT_MASTER); - - public static final WPI_TalonSRX RIGHT_MASTER = CTREControllerFactory.createDefaultTalon(1); - public static final WPI_TalonSRX RIGHT_SLAVE_A = CTREControllerFactory.createPermanentSlaveTalon(2, - RIGHT_MASTER); -// public static final WPI_TalonSRX RIGHT_SLAVE_A = CTREControllerFactory.createDefaultTalon(2); - public static final WPI_VictorSPX RIGHT_SLAVE_B = CTREControllerFactory.createPermanentSlaveVictor(3, - RIGHT_MASTER); -// public static final WPI_VictorSPX RIGHT_SLAVE_B = CTREControllerFactory.createDefaultVictor(3); - - public static final PigeonIMU DRIVETRAIN_IMU = new PigeonIMU(LEFT_SLAVE_A); - - public static final DoubleSolenoid SHIFT_SOLENOID = new DoubleSolenoid(4, 5); - } - - public static final class IntakeMap { - public static final WPI_TalonSRX LEFT_INTAKE = CTREControllerFactory.createDefaultTalon(11); - public static final WPI_TalonSRX RIGHT_INTAKE = CTREControllerFactory.createDefaultTalon(12); - - public static final WPI_TalonSRX LIFT_MOTOR = CTREControllerFactory.createDefaultTalon(13); - - public static final DoubleSolenoid GRAB_SOLENOID = new DoubleSolenoid(2, 3); - } - - public static final class LiftMap { - public static final WPI_TalonSRX MASTER = CTREControllerFactory.createDefaultTalon(8); - public static final WPI_VictorSPX SLAVE = CTREControllerFactory.createPermanentSlaveVictor(7, MASTER); - } - - public static final class ElevatorMap { - public static final WPI_TalonSRX MASTER = CTREControllerFactory.createDefaultTalon(9); - public static final WPI_VictorSPX SLAVE = CTREControllerFactory.createPermanentSlaveVictor(10, MASTER); - } -} +package com.team3925.frc2018; + +import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX; +import com.ctre.phoenix.motorcontrol.can.WPI_VictorSPX; +import com.ctre.phoenix.sensors.PigeonIMU; +import com.team3925.utils.CTREControllerFactory; + +import edu.wpi.first.wpilibj.DoubleSolenoid; + +public class RobotMap { + + public static final class DrivetrainMap { + public static final WPI_TalonSRX LEFT_MASTER = CTREControllerFactory.createDefaultTalon(4); +// public static final WPI_TalonSRX LEFT_SLAVE_A = CTREControllerFactory.createDefaultTalon(5); + public static final WPI_TalonSRX LEFT_SLAVE_A = CTREControllerFactory.createPermanentSlaveTalon(5, LEFT_MASTER); +// public static final WPI_VictorSPX LEFT_SLAVE_B = CTREControllerFactory.createDefaultVictor(6); + public static final WPI_VictorSPX LEFT_SLAVE_B = CTREControllerFactory.createPermanentSlaveVictor(6, + LEFT_MASTER); + + public static final WPI_TalonSRX RIGHT_MASTER = CTREControllerFactory.createDefaultTalon(1); + public static final WPI_TalonSRX RIGHT_SLAVE_A = CTREControllerFactory.createPermanentSlaveTalon(2, + RIGHT_MASTER); +// public static final WPI_TalonSRX RIGHT_SLAVE_A = CTREControllerFactory.createDefaultTalon(2); + public static final WPI_VictorSPX RIGHT_SLAVE_B = CTREControllerFactory.createPermanentSlaveVictor(3, + RIGHT_MASTER); +// public static final WPI_VictorSPX RIGHT_SLAVE_B = CTREControllerFactory.createDefaultVictor(3); + + public static final PigeonIMU DRIVETRAIN_IMU = new PigeonIMU(LEFT_SLAVE_A); + + public static final DoubleSolenoid SHIFT_SOLENOID = new DoubleSolenoid(0, 1); + } + + public static final class IntakeMap { + public static final WPI_TalonSRX LEFT_INTAKE = CTREControllerFactory.createDefaultTalon(11); + public static final WPI_TalonSRX RIGHT_INTAKE = CTREControllerFactory.createDefaultTalon(12); + + public static final WPI_TalonSRX LIFT_MOTOR = CTREControllerFactory.createDefaultTalon(13); + + public static final DoubleSolenoid GRAB_SOLENOID = new DoubleSolenoid(2, 3); + } + + public static final class LiftMap { + public static final WPI_TalonSRX MASTER = CTREControllerFactory.createDefaultTalon(8); + public static final WPI_VictorSPX SLAVE = CTREControllerFactory.createPermanentSlaveVictor(7, MASTER); + } + + public static final class ElevatorMap { + public static final WPI_TalonSRX MASTER = CTREControllerFactory.createDefaultTalon(9); + public static final WPI_VictorSPX SLAVE = CTREControllerFactory.createPermanentSlaveVictor(10, MASTER); + } +} diff --git a/src/com/team3925/frc2018/commands/SetLiftBottom.java b/src/com/team3925/frc2018/commands/SetLiftBottom.java deleted file mode 100644 index 50bf348..0000000 --- a/src/com/team3925/frc2018/commands/SetLiftBottom.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.team3925.frc2018.commands; - -import com.team3925.frc2018.subsystems.Elevator; -import com.team3925.frc2018.subsystems.Elevator.ElevatorState; - -import edu.wpi.first.wpilibj.command.Command; -import edu.wpi.first.wpilibj.command.CommandGroup; - -public class SetLiftBottom extends CommandGroup { - - public SetLiftBottom() { - - addSequential(new Command() { - - @Override - protected void initialize() { - Elevator.getInstance().setPosition(ElevatorState.BOTTOM); - } - - @Override - protected boolean isFinished() { - return Elevator.getInstance().getElevatorHeightPercentage() > 0.10; - } - }); - - addSequential(new Command() { - - @Override - protected boolean isFinished() { - return Elevator.getInstance().getLimitSwitch(); - } - - @Override - protected void initialize() { - Elevator.getInstance().setRaw(-0.2); - } - - @Override - protected void end() { - Elevator.getInstance().setRaw(0); - Elevator.getInstance().zero(); - } - }); - } - -} diff --git a/src/com/team3925/frc2018/commands/SetLiftTop.java b/src/com/team3925/frc2018/commands/SetLiftTop.java deleted file mode 100644 index a652a6f..0000000 --- a/src/com/team3925/frc2018/commands/SetLiftTop.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.team3925.frc2018.commands; - -import com.team3925.frc2018.subsystems.Intake; - -import edu.wpi.first.wpilibj.command.Command; - -public class SetLiftTop extends Command{ - - @Override - protected void initialize() { - Intake.getInstance().setAngle(85); - } - - @Override - protected boolean isFinished() { - return true; - } - - -} diff --git a/src/com/team3925/frc2018/commands/ShootCube.java b/src/com/team3925/frc2018/commands/ShootCube.java index e35ac3a..e2bb4d0 100644 --- a/src/com/team3925/frc2018/commands/ShootCube.java +++ b/src/com/team3925/frc2018/commands/ShootCube.java @@ -1,26 +1,29 @@ -package com.team3925.frc2018.commands; - -import com.team3925.frc2018.subsystems.Intake; - -import edu.wpi.first.wpilibj.command.CommandGroup; -import edu.wpi.first.wpilibj.command.WaitCommand; - -public class ShootCube extends CommandGroup{ - public ShootCube() { - addParallel(new CloseGrabbers()); - addSequential(new RunIntakeWheels(-1)); - addSequential(new WaitCommand(0.5)); - addParallel(new RunIntakeWheels(0)); - } - - @Override - protected void interrupted() { - Intake.getInstance().setGrabber(false); - Intake.getInstance().setIntakeRollers(0); - } - - @Override - protected void end() { - this.interrupted(); - } -} +package com.team3925.frc2018.commands; + +import com.team3925.frc2018.subsystems.Intake; + +import edu.wpi.first.wpilibj.command.CommandGroup; +import edu.wpi.first.wpilibj.command.WaitCommand; + +public class ShootCube extends CommandGroup{ + public ShootCube() { + addParallel(new CloseGrabbers()); + addSequential(new RunIntakeWheels(-1)); + addSequential(new WaitCommand(0.5)); + addParallel(new RunIntakeWheels(0)); + } + + @Override + protected void initialize() { + + } + + @Override + protected void interrupted() { + } + + @Override + protected void end() { + this.interrupted(); + } +} diff --git a/src/com/team3925/frc2018/commands/ZeroIntake.java b/src/com/team3925/frc2018/commands/ZeroIntake.java index 1db12c1..6003e9a 100644 --- a/src/com/team3925/frc2018/commands/ZeroIntake.java +++ b/src/com/team3925/frc2018/commands/ZeroIntake.java @@ -1,30 +1,36 @@ -package com.team3925.frc2018.commands; - -import com.team3925.frc2018.subsystems.Intake; - -import edu.wpi.first.wpilibj.command.Command; - -public class ZeroIntake extends Command { - - @Override - protected boolean isFinished() { - return Intake.getInstance().getLiftMotorLimitSwitch(); - - } - - @Override - protected void execute() { - Intake.getInstance().setLiftMotorRaw(-0.2); - - } - - @Override - protected void end() { - // stop motor - Intake.getInstance().zeroLift(); - Intake.getInstance().setLiftMotorRaw(0); - Intake.getInstance().setAngle(85); - - } - -} +package com.team3925.frc2018.commands; + +import com.team3925.frc2018.subsystems.Intake; + +import edu.wpi.first.wpilibj.Timer; +import edu.wpi.first.wpilibj.command.Command; + +public class ZeroIntake extends Command { + + double startTime; + @Override + protected boolean isFinished() { + return Intake.getInstance().getLiftMotorLimitSwitch() || startTime + 3 > Timer.getFPGATimestamp(); + } + + @Override + protected void execute() { + Intake.getInstance().setLiftMotorRaw(-0.2); + + } + + @Override + protected void end() { + // stop motor + Intake.getInstance().zeroLift(); + Intake.getInstance().setLiftMotorRaw(0); + Intake.getInstance().setAngle(85); + + } + + @Override + protected void initialize() { + startTime = Timer.getFPGATimestamp(); + } + +} diff --git a/src/com/team3925/frc2018/commands/autos/CenterLeftSwitchAuto.java b/src/com/team3925/frc2018/commands/autos/CenterLeftSwitchAuto.java deleted file mode 100644 index 83dd811..0000000 --- a/src/com/team3925/frc2018/commands/autos/CenterLeftSwitchAuto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.team3925.frc2018.commands.autos; - -import com.team3925.frc2018.commands.OpenGrabbers; -import com.team3925.frc2018.commands.RunElevator; -import com.team3925.frc2018.commands.RunIntakeWheels; -import com.team3925.frc2018.commands.ZeroIntake; -import com.team3925.frc2018.subsystems.Elevator.ElevatorState; -import com.team3925.utils.MotionProfileCommand; - -import edu.wpi.first.wpilibj.command.CommandGroup; -import edu.wpi.first.wpilibj.command.WaitCommand; - -public class CenterLeftSwitchAuto extends CommandGroup{ - - public CenterLeftSwitchAuto() { - addSequential(new ZeroIntake()); - addParallel(new RunElevator(ElevatorState.BOTTOM)); - addParallel(new MotionProfileCommand("CENTER_LEFTSWITCH")); - addSequential(new WaitCommand(2)); - addSequential(new RunElevator(ElevatorState.SWITCH)); - addSequential(new OpenGrabbers()); - addSequential(new RunIntakeWheels(-0.5)); - } - -} diff --git a/src/com/team3925/frc2018/commands/autos/CenterRightSwitchAuto.java b/src/com/team3925/frc2018/commands/autos/CenterSwitchAuto.java similarity index 55% rename from src/com/team3925/frc2018/commands/autos/CenterRightSwitchAuto.java rename to src/com/team3925/frc2018/commands/autos/CenterSwitchAuto.java index 6dd0364..7146492 100644 --- a/src/com/team3925/frc2018/commands/autos/CenterRightSwitchAuto.java +++ b/src/com/team3925/frc2018/commands/autos/CenterSwitchAuto.java @@ -1,26 +1,34 @@ -package com.team3925.frc2018.commands.autos; - -import com.team3925.frc2018.commands.OpenGrabbers; -import com.team3925.frc2018.commands.RunElevator; -import com.team3925.frc2018.commands.RunIntakeWheels; -import com.team3925.frc2018.commands.ZeroIntake; -import com.team3925.frc2018.subsystems.Elevator.ElevatorState; -import com.team3925.utils.MotionProfileCommand; - -import edu.wpi.first.wpilibj.command.CommandGroup; -import edu.wpi.first.wpilibj.command.WaitCommand; - -public class CenterRightSwitchAuto extends CommandGroup{ - - public CenterRightSwitchAuto() { - addSequential(new ZeroIntake()); - addParallel(new RunElevator(ElevatorState.BOTTOM)); - addParallel(new MotionProfileCommand("CENTER_RIGHTSWITCH")); - addSequential(new WaitCommand(2)); - addSequential(new RunElevator(ElevatorState.SWITCH)); - addSequential(new OpenGrabbers()); - addSequential(new RunIntakeWheels(-0.5)); - } - -} - +package com.team3925.frc2018.commands.autos; + +import com.team3925.frc2018.commands.CloseGrabbers; +import com.team3925.frc2018.commands.OpenGrabbers; +import com.team3925.frc2018.commands.RunElevator; +import com.team3925.frc2018.commands.RunIntakeWheels; +import com.team3925.frc2018.commands.ZeroIntake; +import com.team3925.frc2018.subsystems.Elevator.ElevatorState; +import com.team3925.utils.MotionProfileCommand; + +import edu.wpi.first.wpilibj.command.CommandGroup; +import edu.wpi.first.wpilibj.command.WaitCommand; + +public class CenterSwitchAuto extends CommandGroup{ + + public enum AutoSide{ + LEFT,RIGHT + } + + public CenterSwitchAuto(AutoSide side) { + addParallel(new CloseGrabbers()); + addParallel(new RunElevator(ElevatorState.SWITCH)); + if (side == AutoSide.LEFT) { + addParallel(new MotionProfileCommand("CENTER_LEFTSWITCH")); + }else { + addParallel(new MotionProfileCommand("CENTER_RIGHTSWITCH")); + } + addSequential(new WaitCommand(2)); + addSequential(new OpenGrabbers()); + addSequential(new RunIntakeWheels(-0.5)); + } + +} + diff --git a/src/com/team3925/frc2018/commands/autos/DriveForwardAuto.java b/src/com/team3925/frc2018/commands/autos/DriveForwardAuto.java new file mode 100644 index 0000000..04284dd --- /dev/null +++ b/src/com/team3925/frc2018/commands/autos/DriveForwardAuto.java @@ -0,0 +1,15 @@ +package com.team3925.frc2018.commands.autos; + +import com.team3925.frc2018.commands.ZeroIntake; +import com.team3925.utils.MotionProfileCommand; + +import edu.wpi.first.wpilibj.command.CommandGroup; + +public class DriveForwardAuto extends CommandGroup{ + + public DriveForwardAuto() { + addParallel(new ZeroIntake()); + addParallel(new MotionProfileCommand("DRIVE_FORWARD")); + } + +} diff --git a/src/com/team3925/frc2018/subsystems/Drivetrain.java b/src/com/team3925/frc2018/subsystems/Drivetrain.java index a9fff0b..1230b50 100644 --- a/src/com/team3925/frc2018/subsystems/Drivetrain.java +++ b/src/com/team3925/frc2018/subsystems/Drivetrain.java @@ -1,177 +1,178 @@ -package com.team3925.frc2018.subsystems; - -import com.ctre.phoenix.motorcontrol.ControlMode; -import com.ctre.phoenix.motorcontrol.FeedbackDevice; -import com.ctre.phoenix.motorcontrol.NeutralMode; -import com.ctre.phoenix.motorcontrol.can.TalonSRX; -import com.team3925.frc2018.Constants; -import com.team3925.frc2018.RobotMap; -import com.team3925.utils.PIDTunable; - -import edu.wpi.first.wpilibj.DoubleSolenoid; -import edu.wpi.first.wpilibj.DoubleSolenoid.Value; -import edu.wpi.first.wpilibj.command.Subsystem; - -public class Drivetrain extends Subsystem implements PIDTunable { - - private final TalonSRX leftMaster = RobotMap.DrivetrainMap.LEFT_MASTER; - - private final TalonSRX rightMaster = RobotMap.DrivetrainMap.RIGHT_MASTER; - - private final DoubleSolenoid shiftSolenoid = RobotMap.DrivetrainMap.SHIFT_SOLENOID; - - public static Drivetrain instance; - private static boolean shiftState = true; - private static final boolean isGyroInverted = false; - - private double kP = 0.2; - private double kI = 0; - private double kD = 0; - private double kF = 0.9; - - private static final NeutralMode drivetrainNeutralMode = NeutralMode.Brake; - - public static Drivetrain getInstance() { - if (instance == null) - instance = new Drivetrain(); - return instance; - } - - private Drivetrain() { - RobotMap.DrivetrainMap.LEFT_MASTER.setInverted(true); - RobotMap.DrivetrainMap.LEFT_SLAVE_A.setInverted(true); - RobotMap.DrivetrainMap.LEFT_SLAVE_B.setInverted(true); - - leftMaster.setSensorPhase(true); - rightMaster.configSelectedFeedbackSensor(FeedbackDevice.QuadEncoder, 0, 10); - leftMaster.configSelectedFeedbackSensor(FeedbackDevice.QuadEncoder, 0, 10); - - leftMaster.config_kF(Constants.PID_ID_X, kF, Constants.TIMEOUT_MS); - leftMaster.config_kP(Constants.PID_ID_X, kP, Constants.TIMEOUT_MS); - leftMaster.config_kI(Constants.PID_ID_X, kI, Constants.TIMEOUT_MS); - leftMaster.config_kD(Constants.PID_ID_X, kD, Constants.TIMEOUT_MS); - - rightMaster.config_kF(Constants.PID_ID_X, kF, Constants.TIMEOUT_MS); - rightMaster.config_kP(Constants.PID_ID_X, kP, Constants.TIMEOUT_MS); - rightMaster.config_kI(Constants.PID_ID_X, kI, Constants.TIMEOUT_MS); - rightMaster.config_kD(Constants.PID_ID_X, kD, Constants.TIMEOUT_MS); - - RobotMap.DrivetrainMap.LEFT_MASTER.setNeutralMode(drivetrainNeutralMode); - RobotMap.DrivetrainMap.LEFT_SLAVE_A.setNeutralMode(drivetrainNeutralMode); - RobotMap.DrivetrainMap.LEFT_SLAVE_B.setNeutralMode(drivetrainNeutralMode); - - RobotMap.DrivetrainMap.LEFT_MASTER.configOpenloopRamp(0.2, Constants.TIMEOUT_MS); - RobotMap.DrivetrainMap.RIGHT_MASTER.configOpenloopRamp(0.2, Constants.TIMEOUT_MS); - - RobotMap.DrivetrainMap.RIGHT_MASTER.setNeutralMode(drivetrainNeutralMode); - RobotMap.DrivetrainMap.RIGHT_SLAVE_A.setNeutralMode(drivetrainNeutralMode); - RobotMap.DrivetrainMap.RIGHT_SLAVE_B.setNeutralMode(drivetrainNeutralMode); - - leftMaster.overrideLimitSwitchesEnable(false); - rightMaster.overrideLimitSwitchesEnable(false); - } - - public void setRaw(double l, double r) { - leftMaster.set(ControlMode.PercentOutput, l); - rightMaster.set(ControlMode.PercentOutput, r); - } - - public void setShifter(boolean isHigh) { - shiftSolenoid.set((isHigh) ? Value.kForward : Value.kReverse); - shiftState = isHigh; - } - - public boolean getShiftState() { - return shiftState; - } - - @Deprecated - public TalonSRX getLeftMaster() { - return leftMaster; - } - - @Deprecated - public TalonSRX getRightMaster() { - return rightMaster; - } - - public void zero() { - leftMaster.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); - rightMaster.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); - - } - - public double getLeftEncoderPosition() { - return leftMaster.getSelectedSensorPosition(Constants.PID_ID_X); - } - - public double getRightEncoderPosition() { - return -rightMaster.getSelectedSensorPosition(Constants.PID_ID_X); - } - - public double getLeftSpeed() { - return leftMaster.getSelectedSensorVelocity(Constants.PID_ID_X); - } - - public double getRightSpeed() { - return -rightMaster.getSelectedSensorVelocity(Constants.PID_ID_X); - } - - public void setVelocity(double l, double r) { - leftMaster.set(ControlMode.Velocity, l); - rightMaster.set(ControlMode.Velocity, r); - } - - public void setRamp(double ramp) { - leftMaster.configOpenloopRamp(ramp, Constants.TIMEOUT_MS); - rightMaster.configOpenloopRamp(ramp, Constants.TIMEOUT_MS); - } - - public double getGyroHeading() { - return ((isGyroInverted) ? -1 : 1) * RobotMap.DrivetrainMap.DRIVETRAIN_IMU.getFusedHeading(); - } - - @Override - protected void initDefaultCommand() { - } - - @Override - public double getkP() { - return kP; - } - - @Override - public void setkP(double kP) { - this.kP = kP; - } - - @Override - public double getkI() { - return kI; - } - - @Override - public void setkI(double kI) { - this.kI = kI; - } - - @Override - public double getkD() { - return kD; - } - - @Override - public void setkD(double kD) { - this.kD = kD; - } - - @Override - public double getkF() { - return kF; - } - - @Override - public void setkF(double kF) { - this.kF = kF; - } -} +package com.team3925.frc2018.subsystems; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.FeedbackDevice; +import com.ctre.phoenix.motorcontrol.NeutralMode; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import com.team3925.frc2018.Constants; +import com.team3925.frc2018.RobotMap; +import com.team3925.utils.PIDTunable; + +import edu.wpi.first.wpilibj.DoubleSolenoid; +import edu.wpi.first.wpilibj.DoubleSolenoid.Value; +import edu.wpi.first.wpilibj.command.Subsystem; + +public class Drivetrain extends Subsystem implements PIDTunable { + + private final TalonSRX leftMaster = RobotMap.DrivetrainMap.LEFT_MASTER; + + private final TalonSRX rightMaster = RobotMap.DrivetrainMap.RIGHT_MASTER; + + private final DoubleSolenoid shiftSolenoid = RobotMap.DrivetrainMap.SHIFT_SOLENOID; + + public static Drivetrain instance; + private static boolean shiftState = true; + private static final boolean isGyroInverted = false; + + private double kP = 0.2; + private double kI = 0; + private double kD = 0; + private double kF = 0.9; + + private static final NeutralMode drivetrainNeutralMode = NeutralMode.Brake; + + public static Drivetrain getInstance() { + if (instance == null) + instance = new Drivetrain(); + return instance; + } + + private Drivetrain() { + RobotMap.DrivetrainMap.LEFT_MASTER.setInverted(true); + RobotMap.DrivetrainMap.LEFT_SLAVE_A.setInverted(true); + RobotMap.DrivetrainMap.LEFT_SLAVE_B.setInverted(true); + + leftMaster.setSensorPhase(true); + rightMaster.setInverted(false); + rightMaster.configSelectedFeedbackSensor(FeedbackDevice.QuadEncoder, 0, 10); + leftMaster.configSelectedFeedbackSensor(FeedbackDevice.QuadEncoder, 0, 10); + + leftMaster.config_kF(Constants.PID_ID_X, kF, Constants.TIMEOUT_MS); + leftMaster.config_kP(Constants.PID_ID_X, kP, Constants.TIMEOUT_MS); + leftMaster.config_kI(Constants.PID_ID_X, kI, Constants.TIMEOUT_MS); + leftMaster.config_kD(Constants.PID_ID_X, kD, Constants.TIMEOUT_MS); + + rightMaster.config_kF(Constants.PID_ID_X, kF, Constants.TIMEOUT_MS); + rightMaster.config_kP(Constants.PID_ID_X, kP, Constants.TIMEOUT_MS); + rightMaster.config_kI(Constants.PID_ID_X, kI, Constants.TIMEOUT_MS); + rightMaster.config_kD(Constants.PID_ID_X, kD, Constants.TIMEOUT_MS); + + RobotMap.DrivetrainMap.LEFT_MASTER.setNeutralMode(drivetrainNeutralMode); + RobotMap.DrivetrainMap.LEFT_SLAVE_A.setNeutralMode(drivetrainNeutralMode); + RobotMap.DrivetrainMap.LEFT_SLAVE_B.setNeutralMode(drivetrainNeutralMode); + + RobotMap.DrivetrainMap.LEFT_MASTER.configOpenloopRamp(0.2, Constants.TIMEOUT_MS); + RobotMap.DrivetrainMap.RIGHT_MASTER.configOpenloopRamp(0.2, Constants.TIMEOUT_MS); + + RobotMap.DrivetrainMap.RIGHT_MASTER.setNeutralMode(drivetrainNeutralMode); + RobotMap.DrivetrainMap.RIGHT_SLAVE_A.setNeutralMode(drivetrainNeutralMode); + RobotMap.DrivetrainMap.RIGHT_SLAVE_B.setNeutralMode(drivetrainNeutralMode); + + leftMaster.overrideLimitSwitchesEnable(false); + rightMaster.overrideLimitSwitchesEnable(false); + } + + public void setRaw(double l, double r) { + leftMaster.set(ControlMode.PercentOutput, l); + rightMaster.set(ControlMode.PercentOutput, r); + } + + public void setShifter(boolean isHigh) { + shiftSolenoid.set((isHigh) ? Value.kForward : Value.kReverse); + shiftState = isHigh; + } + + public boolean getShiftState() { + return shiftState; + } + + @Deprecated + public TalonSRX getLeftMaster() { + return leftMaster; + } + + @Deprecated + public TalonSRX getRightMaster() { + return rightMaster; + } + + public void zero() { + leftMaster.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); + rightMaster.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); + + } + + public double getLeftEncoderPosition() { + return leftMaster.getSelectedSensorPosition(Constants.PID_ID_X); + } + + public double getRightEncoderPosition() { + return -rightMaster.getSelectedSensorPosition(Constants.PID_ID_X); + } + + public double getLeftSpeed() { + return leftMaster.getSelectedSensorVelocity(Constants.PID_ID_X); + } + + public double getRightSpeed() { + return -rightMaster.getSelectedSensorVelocity(Constants.PID_ID_X); + } + + public void setVelocity(double l, double r) { + leftMaster.set(ControlMode.Velocity, l); + rightMaster.set(ControlMode.Velocity, r); + } + + public void setRamp(double ramp) { + leftMaster.configOpenloopRamp(ramp, Constants.TIMEOUT_MS); + rightMaster.configOpenloopRamp(ramp, Constants.TIMEOUT_MS); + } + + public double getGyroHeading() { + return ((isGyroInverted) ? -1 : 1) * RobotMap.DrivetrainMap.DRIVETRAIN_IMU.getFusedHeading(); + } + + @Override + protected void initDefaultCommand() { + } + + @Override + public double getkP() { + return kP; + } + + @Override + public void setkP(double kP) { + this.kP = kP; + } + + @Override + public double getkI() { + return kI; + } + + @Override + public void setkI(double kI) { + this.kI = kI; + } + + @Override + public double getkD() { + return kD; + } + + @Override + public void setkD(double kD) { + this.kD = kD; + } + + @Override + public double getkF() { + return kF; + } + + @Override + public void setkF(double kF) { + this.kF = kF; + } +} diff --git a/src/com/team3925/frc2018/subsystems/Elevator.java b/src/com/team3925/frc2018/subsystems/Elevator.java index d4c05ce..11e6b30 100644 --- a/src/com/team3925/frc2018/subsystems/Elevator.java +++ b/src/com/team3925/frc2018/subsystems/Elevator.java @@ -1,133 +1,132 @@ -package com.team3925.frc2018.subsystems; - -import com.ctre.phoenix.motorcontrol.ControlMode; -import com.ctre.phoenix.motorcontrol.FeedbackDevice; -import com.ctre.phoenix.motorcontrol.can.TalonSRX; -import com.team3925.frc2018.Constants; -import com.team3925.frc2018.RobotMap; - - - -import edu.wpi.first.wpilibj.command.Subsystem; -import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; - -public class Elevator extends Subsystem { - - public enum ElevatorState{ - TOP, SCALE_MAX, SCALE_MED, SCALE_LOW, SWITCH, BOTTOM, UNKNOWN, OTHER; - } - - private final TalonSRX elevatorMaster = RobotMap.ElevatorMap.MASTER; - - private static final double K_ELEVATOR = 1176.48; - - public static final double TELEOP_ELEVATOR_INCREMENT = 8; - - private static final double kP = 0.2; //0.015 | 0.2 - private static final double kI = 0; - private static final double kD = 0; - private static final double kF = 0.35; //0.35 - - private static final int MOTION_MAGIC_ACCELERATION = 9001; - private static final int MOTION_MAGIC_CRUISE_VELOCITY = 5467; -// private static final int MOTION_MAGIC_ACCELERATION = 9001; -// private static final int MOTION_MAGIC_CRUISE_VELOCITY = 5467; -// private static final int MOTION_MAGIC_ACCELERATION = 20594; -// private static final int MOTION_MAGIC_CRUISE_VELOCITY = 5467; - - private static final double MAX_SCALE_HEIGHT = (12 * 5.5) + 4.6667; - public static double elevatorHeight = 0; - - private static Elevator instance; - - public static Elevator getInstance() { - if (instance == null) - instance = new Elevator(); - return instance; - } - - public Elevator() { - elevatorMaster.setInverted(true); - RobotMap.ElevatorMap.SLAVE.setInverted(true); - elevatorMaster.setSensorPhase(true); - elevatorMaster.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, Constants.PID_ID_X, - Constants.TIMEOUT_MS); - - elevatorMaster.selectProfileSlot(0, Constants.PID_ID_X); - elevatorMaster.config_kP(0, kP, Constants.TIMEOUT_MS); - elevatorMaster.config_kI(0, kI, Constants.TIMEOUT_MS); - elevatorMaster.config_kD(0, kD, Constants.TIMEOUT_MS); - elevatorMaster.config_kF(0, kF, Constants.TIMEOUT_MS); - - elevatorMaster.configMotionAcceleration(MOTION_MAGIC_ACCELERATION, Constants.TIMEOUT_MS); - elevatorMaster.configMotionCruiseVelocity(MOTION_MAGIC_CRUISE_VELOCITY, Constants.TIMEOUT_MS); - - elevatorMaster.overrideLimitSwitchesEnable(false); - elevatorMaster.configContinuousCurrentLimit(200, Constants.TIMEOUT_MS); - - elevatorMaster.configNominalOutputForward(0, Constants.TIMEOUT_MS); - elevatorMaster.configNominalOutputReverse(0, Constants.TIMEOUT_MS); - RobotMap.ElevatorMap.SLAVE.configNominalOutputForward(0, Constants.TIMEOUT_MS); - RobotMap.ElevatorMap.SLAVE.configNominalOutputReverse(0, Constants.TIMEOUT_MS); - } - - - public void setRaw(double speed) { - elevatorMaster.set(ControlMode.PercentOutput, speed); - } - - public boolean isElevatorAtSetpoint() { - return elevatorMaster.getClosedLoopError(0) < 100; - } - - public void setPosition(double inches){ -// elevatorMaster.set(ControlMode.Position, (inches * K_ELEVATOR)); - elevatorMaster.set(ControlMode.MotionMagic, (Math.min(inches, MAX_SCALE_HEIGHT) * K_ELEVATOR)); - elevatorHeight = inches; - } - - public void setPosition(ElevatorState state){ - switch(state) { - case TOP: - setPosition((12 * 5.5) + 4.667); - break; - case SCALE_MAX: - setPosition(12 * 5); - break; - case SCALE_MED: - setPosition(12 * 4.5); - break; - case SCALE_LOW: - setPosition(12 * 4); - break; - case BOTTOM: - setPosition(3); - break; - case SWITCH: - setPosition(12 * 2); - break; - } - } - public double getElevatorHeightPercentage() { - return elevatorHeight / MAX_SCALE_HEIGHT; - } - - public void zero() { - elevatorMaster.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); - setPosition(0); - } - - public boolean getLimitSwitch() { - return elevatorMaster.getSensorCollection().isRevLimitSwitchClosed(); - } - - public void log() { - SmartDashboard.putNumber("Elevator Current 1", elevatorMaster.getOutputCurrent()); - SmartDashboard.putNumber("Elevator Current 2", RobotMap.ElevatorMap.SLAVE.getOutputCurrent()); - } - - @Override - protected void initDefaultCommand() { - } - -} +package com.team3925.frc2018.subsystems; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.FeedbackDevice; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import com.team3925.frc2018.Constants; +import com.team3925.frc2018.RobotMap; + +import edu.wpi.first.wpilibj.buttons.Trigger; +import edu.wpi.first.wpilibj.command.Subsystem; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; + +public class Elevator extends Subsystem { + + public enum ElevatorState{ + TOP, SCALE_MAX, SCALE_MED, SCALE_LOW, SWITCH, BOTTOM, UNKNOWN, OTHER; + } + + private final TalonSRX elevatorMaster = RobotMap.ElevatorMap.MASTER; + + private static final double K_ELEVATOR = 1176.48; + + public static final double TELEOP_ELEVATOR_INCREMENT = 8; + + private static final double kP = 0.2; //0.015 | 0.2 + private static final double kI = 0; + private static final double kD = 0; + private static final double kF = 0.35; //0.35 + + private static final int MOTION_MAGIC_ACCELERATION = 9001; + private static final int MOTION_MAGIC_CRUISE_VELOCITY = 5467; +// private static final int MOTION_MAGIC_ACCELERATION = 9001; +// private static final int MOTION_MAGIC_CRUISE_VELOCITY = 5467; +// private static final int MOTION_MAGIC_ACCELERATION = 20594; +// private static final int MOTION_MAGIC_CRUISE_VELOCITY = 5467; + + private static final double MAX_SCALE_HEIGHT = (12 * 5.5) + 4.6667; + public static double elevatorHeight = 0; + + private static Elevator instance; + + public static Elevator getInstance() { + if (instance == null) + instance = new Elevator(); + return instance; + } + + public Elevator() { + elevatorMaster.setInverted(true); + RobotMap.ElevatorMap.SLAVE.setInverted(true); + elevatorMaster.setSensorPhase(true); + elevatorMaster.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, Constants.PID_ID_X, + Constants.TIMEOUT_MS); + + elevatorMaster.selectProfileSlot(0, Constants.PID_ID_X); + elevatorMaster.config_kP(0, kP, Constants.TIMEOUT_MS); + elevatorMaster.config_kI(0, kI, Constants.TIMEOUT_MS); + elevatorMaster.config_kD(0, kD, Constants.TIMEOUT_MS); + elevatorMaster.config_kF(0, kF, Constants.TIMEOUT_MS); + + elevatorMaster.configMotionAcceleration(MOTION_MAGIC_ACCELERATION, Constants.TIMEOUT_MS); + elevatorMaster.configMotionCruiseVelocity(MOTION_MAGIC_CRUISE_VELOCITY, Constants.TIMEOUT_MS); + + elevatorMaster.overrideLimitSwitchesEnable(false); + elevatorMaster.configContinuousCurrentLimit(200, Constants.TIMEOUT_MS); + + elevatorMaster.configNominalOutputForward(0, Constants.TIMEOUT_MS); + elevatorMaster.configNominalOutputReverse(0, Constants.TIMEOUT_MS); + RobotMap.ElevatorMap.SLAVE.configNominalOutputForward(0, Constants.TIMEOUT_MS); + RobotMap.ElevatorMap.SLAVE.configNominalOutputReverse(0, Constants.TIMEOUT_MS); + } + + + public void setRaw(double speed) { + elevatorMaster.set(ControlMode.PercentOutput, speed); + } + + public boolean isElevatorAtSetpoint() { + return elevatorMaster.getClosedLoopError(0) < 100; + } + + public void setPosition(double inches){ +// elevatorMaster.set(ControlMode.Position, (inches * K_ELEVATOR)); + elevatorMaster.set(ControlMode.MotionMagic, (Math.min(inches, MAX_SCALE_HEIGHT) * K_ELEVATOR)); + elevatorHeight = inches; + } + + public void setPosition(ElevatorState state){ + switch(state) { + case TOP: + setPosition((12 * 4.5) + 4.667); + break; + case SCALE_MAX: + setPosition(12 * 4.5); + break; + case SCALE_MED: + setPosition(12 * 4); + break; + case SCALE_LOW: + setPosition(12 * 3.5); + break; + case BOTTOM: + setPosition(0); + break; + case SWITCH: + setPosition(12 * 2); + break; + } + } + public double getElevatorHeightPercentage() { + return elevatorHeight / MAX_SCALE_HEIGHT; + } + + public void zero() { + elevatorMaster.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); +// setPosition(ElevatorState.BOTTOM); + } + + public boolean getLimitSwitch() { + return false; + } + + public void log() { + SmartDashboard.putNumber("Elevator Current 1", elevatorMaster.getOutputCurrent()); + SmartDashboard.putNumber("Elevator Current 2", RobotMap.ElevatorMap.SLAVE.getOutputCurrent()); + } + + @Override + protected void initDefaultCommand() { + } + +} diff --git a/src/com/team3925/frc2018/subsystems/Intake.java b/src/com/team3925/frc2018/subsystems/Intake.java index ba22e21..cc74fd5 100644 --- a/src/com/team3925/frc2018/subsystems/Intake.java +++ b/src/com/team3925/frc2018/subsystems/Intake.java @@ -1,112 +1,118 @@ -package com.team3925.frc2018.subsystems; - -import com.ctre.phoenix.motorcontrol.ControlMode; -import com.ctre.phoenix.motorcontrol.FeedbackDevice; -import com.ctre.phoenix.motorcontrol.can.TalonSRX; -import com.team3925.frc2018.Constants; -import com.team3925.frc2018.RobotMap; - -import edu.wpi.first.wpilibj.DoubleSolenoid; -import edu.wpi.first.wpilibj.DoubleSolenoid.Value; -import edu.wpi.first.wpilibj.command.Subsystem; - -public class Intake extends Subsystem { - - private static final double K_INTAKE = 1504; - private final int LIFT_BIG_GEAR_TEETH = 60; - private final int LIFT_SMALL_GEAR_TEETH = 40; - - private final TalonSRX leftIntake = RobotMap.IntakeMap.LEFT_INTAKE; - - private final TalonSRX rightIntake = RobotMap.IntakeMap.RIGHT_INTAKE; - - private final TalonSRX liftMotor = RobotMap.IntakeMap.LIFT_MOTOR; - - - private final DoubleSolenoid grabSolenoid = RobotMap.IntakeMap.GRAB_SOLENOID; - - private static Intake instance; - - public static Intake getInstance() { - if (instance == null) - instance = new Intake(); - return instance; - } - - private Intake() { - liftMotor.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, Constants.PID_ID_X, - Constants.TIMEOUT_MS); - - liftMotor.selectProfileSlot(0, Constants.PID_ID_X); - liftMotor.config_kP(0, 3, Constants.TIMEOUT_MS); - liftMotor.config_kI(0, 0.01, Constants.TIMEOUT_MS); - liftMotor.config_kD(0, 0, Constants.TIMEOUT_MS); - liftMotor.config_kF(0, 0.35, Constants.TIMEOUT_MS); - - liftMotor.configMotionAcceleration(500, Constants.TIMEOUT_MS); - liftMotor.configMotionCruiseVelocity(700, Constants.TIMEOUT_MS); - - liftMotor.setInverted(true); - liftMotor.setSensorPhase(true); - - leftIntake.setInverted(true); - - } - - private void setPosition(double revolutions) { - liftMotor.set(ControlMode.MotionMagic, (revolutions * Constants.CTRE_ENCODER_TICKS_PER_REV)); - } - - public void setIntakeRollers(double speed) { - if (speed <= 0) - speed = 0.1; - leftIntake.set(ControlMode.PercentOutput, speed); - rightIntake.set(ControlMode.PercentOutput, speed); - } - - public void setLiftMotorRaw(double speed) { - liftMotor.set(ControlMode.PercentOutput, speed); - } - - public boolean getLiftMotorLimitSwitch() { - return liftMotor.getSensorCollection().isRevLimitSwitchClosed(); - } - - public void setGrabber(boolean grab) { - grabSolenoid.set((grab) ? Value.kForward : Value.kReverse); - } - - public double getLiftMotorEncoder() { - return liftMotor.getSelectedSensorPosition(0); - } - - public void setAngle(double degrees) { - liftMotor.set(ControlMode.MotionMagic, (degrees/90) * K_INTAKE); -// setPosition(((degrees / 360) * (LIFT_BIG_GEAR_TEETH / LIFT_SMALL_GEAR_TEETH)) * Constants.CTRE_ENCODER_TICKS_PER_REV); - } - - public double getPosition() { - return liftMotor.getSelectedSensorPosition(0); - } - - public void zeroLift() { - liftMotor.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); - } - - @Override - protected void initDefaultCommand() { - } - - public double getLeftCurrent() { - - return leftIntake.getOutputCurrent(); - - } - - public double getRightCurrent() { - - return rightIntake.getOutputCurrent(); - - } - -} +package com.team3925.frc2018.subsystems; + +import com.ctre.phoenix.motorcontrol.ControlMode; +import com.ctre.phoenix.motorcontrol.FeedbackDevice; +import com.ctre.phoenix.motorcontrol.can.TalonSRX; +import com.team3925.frc2018.Constants; +import com.team3925.frc2018.RobotMap; + +import edu.wpi.first.wpilibj.DoubleSolenoid; +import edu.wpi.first.wpilibj.DoubleSolenoid.Value; +import edu.wpi.first.wpilibj.command.Subsystem; + +public class Intake extends Subsystem { + + private static final double K_INTAKE = 1504; + private final int LIFT_BIG_GEAR_TEETH = 60; + private final int LIFT_SMALL_GEAR_TEETH = 40; + + private double currentSetpoint = 0; + + private final TalonSRX leftIntake = RobotMap.IntakeMap.LEFT_INTAKE; + + private final TalonSRX rightIntake = RobotMap.IntakeMap.RIGHT_INTAKE; + + private final TalonSRX liftMotor = RobotMap.IntakeMap.LIFT_MOTOR; + + + private final DoubleSolenoid grabSolenoid = RobotMap.IntakeMap.GRAB_SOLENOID; + + private static Intake instance; + + public static Intake getInstance() { + if (instance == null) + instance = new Intake(); + return instance; + } + + private Intake() { + liftMotor.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, Constants.PID_ID_X, + Constants.TIMEOUT_MS); + + liftMotor.selectProfileSlot(0, Constants.PID_ID_X); + liftMotor.config_kP(0, 3, Constants.TIMEOUT_MS); + liftMotor.config_kI(0, 0.01, Constants.TIMEOUT_MS); + liftMotor.config_kD(0, 0, Constants.TIMEOUT_MS); + liftMotor.config_kF(0, 0.35, Constants.TIMEOUT_MS); + + liftMotor.configMotionAcceleration(300, Constants.TIMEOUT_MS); + liftMotor.configMotionCruiseVelocity(500, Constants.TIMEOUT_MS); + liftMotor.setInverted(true); + liftMotor.setSensorPhase(true); + liftMotor.overrideLimitSwitchesEnable(true); + liftMotor.configContinuousCurrentLimit(10, Constants.TIMEOUT_MS) + leftIntake.setInverted(true); + } + + private void setPosition(double revolutions) { + liftMotor.set(ControlMode.MotionMagic, (revolutions * Constants.CTRE_ENCODER_TICKS_PER_REV)); + } + + public void setIntakeRollers(double speed) { + if (Math.abs(speed) <= 0) + speed = 0.3; + leftIntake.set(ControlMode.PercentOutput, speed); + rightIntake.set(ControlMode.PercentOutput, speed); + } + + public void setLiftMotorRaw(double speed) { + liftMotor.set(ControlMode.PercentOutput, speed); + } + + public boolean getLiftMotorLimitSwitch() { + return liftMotor.getSensorCollection().isRevLimitSwitchClosed(); + } + + public void setGrabber(boolean grab) { + grabSolenoid.set((grab) ? Value.kForward : Value.kReverse); + } + + public boolean isAtSetpoint() { + return Math.abs(liftMotor.getSelectedSensorPosition(0) - currentSetpoint) < 750; + } + + public double getLiftMotorEncoder() { + return liftMotor.getSelectedSensorPosition(0); + } + + public void setAngle(double degrees) { + liftMotor.set(ControlMode.MotionMagic, (-(90-degrees)/90) * K_INTAKE); + currentSetpoint = (-(90-degrees)/90) * K_INTAKE; +// setPosition(((degrees / 360) * (LIFT_BIG_GEAR_TEETH / LIFT_SMALL_GEAR_TEETH)) * Constants.CTRE_ENCODER_TICKS_PER_REV); + } + + public double getPosition() { + return liftMotor.getSelectedSensorPosition(0); + } + + public void zeroLift() { + liftMotor.setSelectedSensorPosition(0, Constants.PID_ID_X, Constants.TIMEOUT_MS); + } + + @Override + protected void initDefaultCommand() { + } + + public double getLeftCurrent() { + + return leftIntake.getOutputCurrent(); + + } + + public double getRightCurrent() { + + return rightIntake.getOutputCurrent(); + + } + +} diff --git a/src/com/team3925/utils/GnarlyController.java b/src/com/team3925/utils/GnarlyController.java index 902b284..2d2f2dc 100644 --- a/src/com/team3925/utils/GnarlyController.java +++ b/src/com/team3925/utils/GnarlyController.java @@ -1,188 +1,188 @@ -package com.team3925.utils; - -import edu.wpi.first.wpilibj.Timer; -import jaci.pathfinder.Pathfinder; -import jaci.pathfinder.Trajectory; - -public class GnarlyController { - - boolean leftSide; - double gyro_offset; - - int encoder_offset, encoder_tick_count; - double wheel_circumference; - - double kp, ki, kd, kv, ka, kg; - - double last_error, last_time; - - double[] position_log = new double[2]; - double[] angle_log = new double[2]; - double[] velocity_log = new double[2]; - - int segment; - Trajectory trajectory; - - public GnarlyController(Trajectory traj) { - this.trajectory = traj; - } - - public void setTrajectory(Trajectory traj) { - this.trajectory = traj; - reset(); - } - - /** - * Configure the PID/VA Variables for the Follower - * - * @param kp - * The proportional term. This is usually quite high (0.8 - 1.0 are - * common values) - * @param ki - * The integral term. Currently unused. - * @param kd - * The derivative term. Adjust this if you are unhappy with the - * tracking of the follower. 0.0 is the default - * @param kv - * The velocity ratio. This should be 1 over your maximum velocity @ - * 100% throttle. This converts m/s given by the algorithm to a scale - * of -1..1 to be used by your motor controllers - * @param ka - * The acceleration term. Adjust this if you want to reach higher or - * lower speeds faster. 0.0 is the default - * @param kg - * The gyro term. This makes your robot more aggressively track its - * heading. - */ - public void configurePIDVAG(double kp, double ki, double kd, double kv, double ka, double kg) { - this.kp = kp; - this.ki = ki; - this.kd = kd; - this.kv = kv; - this.ka = ka; - this.kg = kg; - } - - /** - * Configure the Encoders and gyro being used in the follower. - * - * @param initial_position - * The initial 'offset' of your encoder. This should be set to the - * encoder value just before you start to track - * @param ticks_per_revolution - * How many ticks per revolution the encoder has - * @param wheel_diameter - * The diameter of your wheels (or pulleys for track systems) in - * meters - * @param leftSide - * Used to calculate gyro heading in closed loop mode - * @param initial_position - * The initial 'offset' of your gyro. This should be set to the gyro - * value just before you start to track - */ - public void config(int initial_position, int ticks_per_revolution, double wheel_diameter, boolean leftSide, double initial_angle) { - if (leftSide) { - this.leftSide = true; - } else { - this.leftSide = false; - } - this.encoder_offset = initial_position; - this.encoder_tick_count = ticks_per_revolution; - this.wheel_circumference = Math.PI * wheel_diameter; - this.gyro_offset = initial_angle; - } - - - /** - * Reset the follower to start again. Encoders must be reconfigured. - */ - public void reset() { - last_error = 0; - segment = 0; - } - - /** - * Calculate the desired output for the motors, based on the amount of ticks the - * encoder has gone through. This does not account for heading of the robot. To - * account for heading, add some extra terms in your control loop for - * realignment based on gyroscope input and the desired heading given by this - * object. - * - * @param encoder_tick - * The amount of ticks the encoder has currently measured. - * @param gyro_heading - * The angle the gyro currently measures. - * @return The desired output for your motor controller - */ - - public double calculate(int encoder_tick, double gyro_heading, double encoder_vel_tpr) { - // Number of Revolutions * Wheel Circumference - - if (last_time == 0) { - last_time = Timer.getFPGATimestamp(); - } - - if (segment < trajectory.length()) { - - Trajectory.Segment seg = trajectory.get(segment); - - double distance_covered = ((encoder_tick - encoder_offset) / encoder_tick_count) * wheel_circumference; - double enc_vel = encoder_vel_tpr / encoder_tick_count * wheel_circumference * 10; - - double positionError = seg.position - distance_covered; - double velocityError = seg.velocity - enc_vel; - // Clockwise creates a negative heading - double headingError = Pathfinder.r2d(seg.heading) - Pathfinder.boundHalfDegrees(gyro_heading - gyro_offset); - - // Loop is Velocity_Set_Point + Gyro_Error + Position_Error + Velocity_Error - double calculated_value = seg.velocity + seg.acceleration * ka + (leftSide ? -1.0 : 1.0) * kg * headingError + kp * positionError + kv * velocityError; - // Convert Ft/S to RPM - double converted_value = calculated_value / 10 / wheel_circumference * encoder_tick_count; - - //LOG - position_log[0] = seg.position; - position_log[1] = distance_covered; - angle_log[0] = Pathfinder.boundHalfDegrees(Pathfinder.r2d(seg.heading)); - angle_log[1] = Pathfinder.boundHalfDegrees(gyro_heading - gyro_offset); - velocity_log[0] = seg.velocity; - velocity_log[1] = enc_vel; - - - double dt = Timer.getFPGATimestamp() - last_time; - if (dt >= seg.dt) { - segment++; - last_time = Timer.getFPGATimestamp(); - } - return converted_value; - } else { - return 0; - } - } - - public double[] logPosition() { - return position_log; - } - - public double[] logAngle() { - return angle_log; - } - - public double[] logVelocity() { - return velocity_log; - } - - /** - * @return the current segment being operated on - */ - public Trajectory.Segment getSegment() { - return trajectory.get(segment); - } - - /** - * @return whether we have finished tracking this trajectory or not. - */ - public boolean isFinished() { - return segment >= trajectory.length(); - } - -} +package com.team3925.utils; + +import edu.wpi.first.wpilibj.Timer; +import jaci.pathfinder.Pathfinder; +import jaci.pathfinder.Trajectory; + +public class GnarlyController { + + boolean leftSide; + double gyro_offset; + + int encoder_offset, encoder_tick_count; + double wheel_circumference; + + double kp, ki, kd, kv, ka, kg; + + double last_error, last_time; + + double[] position_log = new double[2]; + double[] angle_log = new double[2]; + double[] velocity_log = new double[2]; + + int segment; + Trajectory trajectory; + + public GnarlyController(Trajectory traj) { + this.trajectory = traj; + } + + public void setTrajectory(Trajectory traj) { + this.trajectory = traj; + reset(); + } + + /** + * Configure the PID/VA Variables for the Follower + * + * @param kp + * The proportional term. This is usually quite high (0.8 - 1.0 are + * common values) + * @param ki + * The integral term. Currently unused. + * @param kd + * The derivative term. Adjust this if you are unhappy with the + * tracking of the follower. 0.0 is the default + * @param kv + * The velocity ratio. This should be 1 over your maximum velocity @ + * 100% throttle. This converts m/s given by the algorithm to a scale + * of -1..1 to be used by your motor controllers + * @param ka + * The acceleration term. Adjust this if you want to reach higher or + * lower speeds faster. 0.0 is the default + * @param kg + * The gyro term. This makes your robot more aggressively track its + * heading. + */ + public void configurePIDVAG(double kp, double ki, double kd, double kv, double ka, double kg) { + this.kp = kp; + this.ki = ki; + this.kd = kd; + this.kv = kv; + this.ka = ka; + this.kg = kg; + } + + /** + * Configure the Encoders and gyro being used in the follower. + * + * @param initial_position + * The initial 'offset' of your encoder. This should be set to the + * encoder value just before you start to track + * @param ticks_per_revolution + * How many ticks per revolution the encoder has + * @param wheel_diameter + * The diameter of your wheels (or pulleys for track systems) in + * meters + * @param leftSide + * Used to calculate gyro heading in closed loop mode + * @param initial_position + * The initial 'offset' of your gyro. This should be set to the gyro + * value just before you start to track + */ + public void config(int initial_position, int ticks_per_revolution, double wheel_diameter, boolean leftSide, double initial_angle) { + if (leftSide) { + this.leftSide = true; + } else { + this.leftSide = false; + } + this.encoder_offset = initial_position; + this.encoder_tick_count = ticks_per_revolution; + this.wheel_circumference = Math.PI * wheel_diameter; + this.gyro_offset = initial_angle; + } + + + /** + * Reset the follower to start again. Encoders must be reconfigured. + */ + public void reset() { + last_error = 0; + segment = 0; + } + + /** + * Calculate the desired output for the motors, based on the amount of ticks the + * encoder has gone through. This does not account for heading of the robot. To + * account for heading, add some extra terms in your control loop for + * realignment based on gyroscope input and the desired heading given by this + * object. + * + * @param encoder_tick + * The amount of ticks the encoder has currently measured. + * @param gyro_heading + * The angle the gyro currently measures. + * @return The desired output for your motor controller + */ + + public double calculate(int encoder_tick, double gyro_heading, double encoder_vel_tpr) { + // Number of Revolutions * Wheel Circumference + + if (last_time == 0) { + last_time = Timer.getFPGATimestamp(); + } + + if (segment < trajectory.length()) { + + Trajectory.Segment seg = trajectory.get(segment); + + double distance_covered = ((encoder_tick - encoder_offset) / encoder_tick_count) * wheel_circumference; + double enc_vel = encoder_vel_tpr / encoder_tick_count * wheel_circumference * 10; + + double positionError = seg.position - distance_covered; + double velocityError = seg.velocity - enc_vel; + // Clockwise creates a negative heading + double headingError = Pathfinder.boundHalfDegrees(Pathfinder.r2d(seg.heading) - (gyro_heading - gyro_offset)); + + // Loop is Velocity_Set_Point + Gyro_Error + Position_Error + Velocity_Error + double calculated_value = seg.velocity + seg.acceleration * ka + (leftSide ? -1.0 : 1.0) * kg * headingError + kp * positionError + kv * velocityError; + // Convert Ft/S to RPM + double converted_value = calculated_value / 10 / wheel_circumference * encoder_tick_count; + + //LOG + position_log[0] = seg.position; + position_log[1] = distance_covered; + angle_log[0] = Pathfinder.boundHalfDegrees(Pathfinder.r2d(seg.heading)); + angle_log[1] = Pathfinder.boundHalfDegrees(gyro_heading - gyro_offset); + velocity_log[0] = seg.velocity; + velocity_log[1] = enc_vel; + + + double dt = Timer.getFPGATimestamp() - last_time; + if (dt >= seg.dt) { + segment++; + last_time = Timer.getFPGATimestamp(); + } + return converted_value; + } else { + return 0; + } + } + + public double[] logPosition() { + return position_log; + } + + public double[] logAngle() { + return angle_log; + } + + public double[] logVelocity() { + return velocity_log; + } + + /** + * @return the current segment being operated on + */ + public Trajectory.Segment getSegment() { + return trajectory.get(segment); + } + + /** + * @return whether we have finished tracking this trajectory or not. + */ + public boolean isFinished() { + return segment >= trajectory.length(); + } + +}