wh1ter0se /
PowerUp-2018
| 1 | package org.usfirst.frc.team3695.robot.subsystems; |
||
| 2 | |||
| 3 | import com.ctre.phoenix.motorcontrol.ControlMode; |
||
| 4 | import com.ctre.phoenix.motorcontrol.FeedbackDevice; |
||
| 5 | import com.ctre.phoenix.motorcontrol.StatusFrameEnhanced; |
||
| 6 | import com.ctre.phoenix.motorcontrol.can.TalonSRX; |
||
| 7 | import edu.wpi.first.wpilibj.BuiltInAccelerometer; |
||
| 8 | import edu.wpi.first.wpilibj.Joystick; |
||
| 9 | import edu.wpi.first.wpilibj.command.Subsystem; |
||
| 10 | import edu.wpi.first.wpilibj.interfaces.Accelerometer; |
||
| 11 | import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; |
||
| 12 | |||
| 13 | import org.usfirst.frc.team3695.robot.Constants; |
||
| 14 | import org.usfirst.frc.team3695.robot.Robot; |
||
| 15 | import org.usfirst.frc.team3695.robot.commands.ManualCommandDrive; |
||
| 16 | import org.usfirst.frc.team3695.robot.enumeration.Bot; |
||
| 17 | import org.usfirst.frc.team3695.robot.enumeration.Drivetrain; |
||
| 18 | import org.usfirst.frc.team3695.robot.util.Xbox; |
||
| 19 | |||
| 20 | /** VROOM VROOM */ |
||
| 21 | public class SubsystemDrive extends Subsystem {
|
||
| 22 | |||
| 23 | |||
| 24 | private static TalonSRX leftMaster; |
||
| 25 | private static TalonSRX leftSlave; |
||
| 26 | private static TalonSRX rightMaster; |
||
| 27 | private static TalonSRX rightSlave; |
||
| 28 | |||
| 29 | public Drivetrain drivetrain; |
||
| 30 | |||
| 31 | public static boolean reversing; |
||
|
0 ignored issues
–
show
|
|||
| 32 | public static boolean docking; |
||
|
0 ignored issues
–
show
public static fields should always be marked final to prevent them being overwritten in unexpected ways. Consider making
docking final.
Loading history...
|
|||
| 33 | private static double dockInhibitor; |
||
| 34 | |||
| 35 | private Accelerometer accel; |
||
| 36 | |||
| 37 | public PID pid; // instantiate innerclass |
||
| 38 | |||
| 39 | /* Allowable tolerance to be considered in range when driving a distance, in rotations */ |
||
| 40 | public static final double DISTANCE_ALLOWABLE_ERROR = SubsystemDrive.in2rot(2.0); |
||
| 41 | |||
| 42 | /* runs at robot boot */ |
||
| 43 | public void initDefaultCommand() {
|
||
| 44 | setDefaultCommand(new ManualCommandDrive()); |
||
| 45 | } |
||
| 46 | |||
| 47 | /* converts left magnetic encoder's magic units to inches */ |
||
| 48 | public static double leftMag2In(double leftMag) {
|
||
| 49 | return leftMag / 212; |
||
|
0 ignored issues
–
show
|
|||
| 50 | } |
||
| 51 | |||
| 52 | /* converts right magnetic encoder's magic units to inches */ |
||
| 53 | public static double rightMag2In(double rightMag) {
|
||
| 54 | return rightMag / 212; |
||
|
0 ignored issues
–
show
|
|||
| 55 | } |
||
| 56 | |||
| 57 | /* converts left magnetic encoder's magic units to inches */ |
||
| 58 | public static double leftIn2Mag(double leftMag) {
|
||
| 59 | return leftMag * 212; |
||
|
0 ignored issues
–
show
|
|||
| 60 | } |
||
| 61 | |||
| 62 | /* converts right magnetic encoder's magic units to inches */ |
||
| 63 | public static double rightIn2Mag(double rightMag) {
|
||
| 64 | // return rightMag * Constants.RIGHT_MAGIC_PER_INCHES; |
||
| 65 | return rightMag * 212; |
||
|
0 ignored issues
–
show
|
|||
| 66 | } |
||
| 67 | |||
| 68 | /* converts RPM to inches per second */ |
||
| 69 | public static double rpm2ips(double rpm) {
|
||
| 70 | return rpm / 60.0 * Constants.WHEEL_DIAMETER * Math.PI; |
||
|
0 ignored issues
–
show
|
|||
| 71 | } |
||
| 72 | |||
| 73 | /* converts an inches per second number to RPM */ |
||
| 74 | public static double ips2rpm(double ips) {
|
||
| 75 | return ips * 60.0 / Constants.WHEEL_DIAMETER / Math.PI; |
||
|
0 ignored issues
–
show
|
|||
| 76 | } |
||
| 77 | |||
| 78 | /* converts rotations to distance traveled in inches */ |
||
| 79 | public static double rot2in(double rot) {
|
||
| 80 | return rot * Constants.WHEEL_DIAMETER * Math.PI; |
||
| 81 | } |
||
| 82 | |||
| 83 | /* converts distance traveled in inches to rotations */ |
||
| 84 | public static double in2rot(double in) {
|
||
| 85 | return in / Constants.WHEEL_DIAMETER / Math.PI; |
||
| 86 | } |
||
| 87 | |||
| 88 | |||
| 89 | |||
| 90 | |||
| 91 | /* apply left motor invert */ |
||
| 92 | public static final double leftify(double left) {
|
||
| 93 | Boolean invert = Robot.bot == Bot.OOF ? Constants.OOF.LEFT_MOTOR_INVERT : Constants.TEUFELSKIND.LEFT_MOTOR_INVERT; |
||
| 94 | return left * (invert ? -1.0 : 1.0) * (docking ? dockInhibitor : 1); |
||
| 95 | } |
||
| 96 | |||
| 97 | /* apply right motor invert */ |
||
| 98 | public static final double rightify(double right) {
|
||
| 99 | Boolean invert = Robot.bot == Bot.OOF ? Constants.OOF.RIGHT_MOTOR_INVERT : Constants.TEUFELSKIND.RIGHT_MOTOR_INVERT; |
||
| 100 | return right * (invert ? -1.0 : 1.0) * (docking ? dockInhibitor : 1); |
||
| 101 | } |
||
| 102 | |||
| 103 | |||
| 104 | |||
| 105 | /** |
||
| 106 | * gives birth to the talons and instantiates variables (including the Bot enum) |
||
| 107 | */ |
||
| 108 | public SubsystemDrive() {
|
||
| 109 | |||
| 110 | accel = new BuiltInAccelerometer(); |
||
| 111 | |||
| 112 | drivetrain = Drivetrain.ROCKET_LEAGUE; |
||
| 113 | |||
| 114 | reversing = false; |
||
| 115 | docking = false; |
||
| 116 | dockInhibitor = 0.5d; |
||
|
0 ignored issues
–
show
|
|||
| 117 | |||
| 118 | pid = new PID(); |
||
| 119 | |||
| 120 | // masters |
||
| 121 | leftMaster = new TalonSRX(Constants.LEFT_MASTER); |
||
|
0 ignored issues
–
show
|
|||
| 122 | leftMaster.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, Constants.LEFT_PID, Constants.TIMEOUT_PID); |
||
| 123 | rightMaster = new TalonSRX(Constants.RIGHT_MASTER); |
||
|
0 ignored issues
–
show
|
|||
| 124 | rightMaster.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, Constants.RIGHT_PID, Constants.TIMEOUT_PID); |
||
| 125 | |||
| 126 | // slaves |
||
| 127 | leftSlave = new TalonSRX(Constants.LEFT_SLAVE); |
||
|
0 ignored issues
–
show
|
|||
| 128 | leftSlave.follow(leftMaster); |
||
| 129 | rightSlave = new TalonSRX(Constants.RIGHT_SLAVE); |
||
|
0 ignored issues
–
show
|
|||
| 130 | rightSlave.follow(rightMaster); |
||
| 131 | |||
| 132 | switch (Robot.bot){
|
||
| 133 | case TEUFELSKIND: |
||
| 134 | PID.setPIDF(Constants.TEUFELSKIND.P, Constants.TEUFELSKIND.I, Constants.TEUFELSKIND.D, Constants.TEUFELSKIND.F); |
||
| 135 | break; |
||
| 136 | case OOF: |
||
| 137 | PID.setPIDF(Constants.OOF.P, Constants.OOF.I, Constants.OOF.D, Constants.OOF.F); |
||
| 138 | break; |
||
| 139 | } |
||
| 140 | } |
||
| 141 | |||
| 142 | public void setDrivetrain(Drivetrain drivetrain) {
|
||
| 143 | this.drivetrain = drivetrain; |
||
| 144 | } |
||
| 145 | |||
| 146 | public void toggleDocking(double dockInhibitor){
|
||
| 147 | docking = !docking; |
||
|
0 ignored issues
–
show
|
|||
| 148 | this.dockInhibitor = dockInhibitor; |
||
|
0 ignored issues
–
show
|
|||
| 149 | } |
||
| 150 | |||
| 151 | public void toggleReversing(){
|
||
| 152 | reversing = !reversing; |
||
|
0 ignored issues
–
show
|
|||
| 153 | } |
||
| 154 | |||
| 155 | public double getYAngle() {
|
||
| 156 | //http://www.hobbytronics.co.uk/accelerometer-info |
||
| 157 | //Formula for getting the angle through the accelerometer |
||
| 158 | //arctan returns in radians so we convert to degrees. |
||
| 159 | return Math.atan(accel.getY() / Math.sqrt(Math.pow(accel.getX(), 2) + Math.pow(accel.getZ(), 2))) * 180 / Math.PI; |
||
|
0 ignored issues
–
show
|
|||
| 160 | } |
||
| 161 | |||
| 162 | |||
| 163 | |||
| 164 | /** |
||
| 165 | * simple rocket league drive code (not actually rocket league) |
||
| 166 | * independent rotation and acceleration |
||
| 167 | */ |
||
| 168 | public void driveRLTank(Joystick joy, double ramp, double inhibitor) {
|
||
| 169 | double adder = Xbox.RT(joy) - Xbox.LT(joy); |
||
| 170 | double left = adder + (Xbox.LEFT_X(joy) / 1.333333); |
||
|
0 ignored issues
–
show
|
|||
| 171 | double right = adder - (Xbox.LEFT_X(joy) / 1.333333); |
||
|
0 ignored issues
–
show
|
|||
| 172 | left = (left > 1.0 ? 1.0 : (left < -1.0 ? -1.0 : left)); |
||
| 173 | right = (right > 1.0 ? 1.0 : (right < -1.0 ? -1.0 : right)); |
||
| 174 | setRamps(ramp); |
||
| 175 | |||
| 176 | // if (getYAngle() > Constants.TILT_ANGLE ) {
|
||
| 177 | // leftMaster.set(ControlMode.PercentOutput, -1*Constants.RECOVERY_SPEED); |
||
| 178 | // rightMaster.set(ControlMode.PercentOutput, -1*Constants.RECOVERY_SPEED); |
||
| 179 | // } else if (getYAngle() < -1*Constants.TILT_ANGLE){
|
||
| 180 | // leftMaster.set(ControlMode.PercentOutput, Constants.RECOVERY_SPEED); |
||
| 181 | // rightMaster.set(ControlMode.PercentOutput, Constants.RECOVERY_SPEED); |
||
| 182 | // } else {
|
||
| 183 | leftMaster.set(ControlMode.PercentOutput, leftify(left)); |
||
| 184 | rightMaster.set(ControlMode.PercentOutput, rightify(right)); |
||
| 185 | // } |
||
| 186 | } |
||
| 187 | |||
| 188 | /** |
||
| 189 | * drive code where rotation is dependent on acceleration |
||
| 190 | * @param radius 0.00-1.00, 1 being zero radius and 0 being driving in a line |
||
| 191 | */ |
||
| 192 | public void driveForza(Joystick joy, double ramp, double radius, double inhibitor) {
|
||
| 193 | double left = 0, |
||
| 194 | right = 0; |
||
|
0 ignored issues
–
show
|
|||
| 195 | double acceleration = Xbox.RT(joy) - Xbox.LT(joy); |
||
| 196 | |||
| 197 | setRamps(ramp); |
||
| 198 | // if (getYAngle() > Constants.TILT_ANGLE ) {
|
||
| 199 | // leftMaster.set(ControlMode.PercentOutput, -1 * Constants.RECOVERY_SPEED); |
||
| 200 | // rightMaster.set(ControlMode.PercentOutput, -1 * Constants.RECOVERY_SPEED); |
||
| 201 | // } else if (getYAngle() < -1 * Constants.TILT_ANGLE){
|
||
| 202 | // leftMaster.set(ControlMode.PercentOutput, Constants.RECOVERY_SPEED); |
||
| 203 | // rightMaster.set(ControlMode.PercentOutput, Constants.RECOVERY_SPEED); |
||
| 204 | // } else {
|
||
| 205 | |||
| 206 | if (!reversing ? Xbox.LEFT_X(joy) < 0 : Xbox.LEFT_X(joy) > 0) {
|
||
|
0 ignored issues
–
show
|
|||
| 207 | right = acceleration; |
||
| 208 | left = (acceleration * ((2 * (1 - Math.abs(Xbox.LEFT_X(joy)))) - 1)) / radius; |
||
|
0 ignored issues
–
show
|
|||
| 209 | } else if (!reversing ? Xbox.LEFT_X(joy) > 0 : Xbox.LEFT_X(joy) < 0) {
|
||
|
0 ignored issues
–
show
|
|||
| 210 | left = acceleration; |
||
| 211 | right = (acceleration * ((2 * (1 - Math.abs(Xbox.LEFT_X(joy)))) - 1)) / radius; |
||
|
0 ignored issues
–
show
|
|||
| 212 | } else {
|
||
| 213 | left = acceleration; |
||
| 214 | right = acceleration; |
||
| 215 | } |
||
| 216 | // }][\ |
||
| 217 | left = (left > 1.0 ? 1.0 : (left < -1.0 ? -1.0 : left)); |
||
| 218 | right = (right > 1.0 ? 1.0 : (right < -1.0 ? -1.0 : right)); |
||
| 219 | leftMaster.set(ControlMode.PercentOutput, leftify(left) * inhibitor * (reversing ? -1.0 : 1.0)); |
||
| 220 | rightMaster.set(ControlMode.PercentOutput, rightify(right) * inhibitor * (reversing ? -1.0 : 1.0)); |
||
| 221 | |||
| 222 | SmartDashboard.putString("Left Master", "Left Master Voltage: " + leftMaster.getBusVoltage());
|
||
| 223 | SmartDashboard.putString("Right Master", "Right Master Voltage: " + rightMaster.getBusVoltage());
|
||
| 224 | } |
||
| 225 | |||
| 226 | |||
| 227 | |||
| 228 | public void setRamps(double ramp) {
|
||
| 229 | if (leftMaster != null) |
||
| 230 | leftMaster.configOpenloopRamp(ramp, 10); |
||
|
0 ignored issues
–
show
|
|||
| 231 | if (leftSlave != null) |
||
| 232 | leftSlave.configOpenloopRamp(ramp, 10); |
||
|
0 ignored issues
–
show
|
|||
| 233 | if (rightMaster != null) |
||
| 234 | rightMaster.configOpenloopRamp(ramp, 10); |
||
|
0 ignored issues
–
show
|
|||
| 235 | if (rightSlave != null) |
||
| 236 | rightSlave.configOpenloopRamp(ramp, 10); |
||
|
0 ignored issues
–
show
|
|||
| 237 | } |
||
| 238 | |||
| 239 | |||
| 240 | |||
| 241 | public boolean driveDistance(double leftIn, double rightIn) {
|
||
| 242 | double leftGoal = (leftIn2Mag(leftIn)); |
||
| 243 | double rightGoal = (rightIn2Mag(rightIn)); |
||
| 244 | leftMaster.set(ControlMode.Position, leftify(leftGoal)); |
||
| 245 | leftSlave.follow(leftMaster); |
||
| 246 | rightMaster.set(ControlMode.Position, rightify(rightGoal)); |
||
| 247 | rightSlave.follow(rightMaster); |
||
| 248 | |||
| 249 | boolean leftInRange = |
||
| 250 | pid.getLeftInches() > leftify(leftGoal) - DISTANCE_ALLOWABLE_ERROR && |
||
| 251 | pid.getLeftInches() < leftify(leftGoal) + DISTANCE_ALLOWABLE_ERROR; |
||
| 252 | boolean rightInRange = |
||
| 253 | pid.getRightInches() > rightify(rightGoal) - DISTANCE_ALLOWABLE_ERROR && |
||
| 254 | pid.getRightInches() < rightify(rightGoal) + DISTANCE_ALLOWABLE_ERROR; |
||
| 255 | return leftInRange && rightInRange; |
||
| 256 | } |
||
| 257 | |||
| 258 | public void driveDirect(double left, double right) {
|
||
| 259 | left = (left > 1.0 ? 1.0 : (left < -1.0 ? -1.0 : left)); |
||
| 260 | right = (right > 1.0 ? 1.0 : (right < -1.0 ? -1.0 : right)); |
||
| 261 | leftMaster.set(ControlMode.PercentOutput, leftify(left)); |
||
| 262 | rightMaster.set(ControlMode.PercentOutput, rightify(right)); |
||
| 263 | } |
||
| 264 | |||
| 265 | public void setInverts() {
|
||
| 266 | rightMaster.setInverted(Robot.bot == Bot.OOF ? Constants.OOF.RIGHT_MASTER_INVERT : Constants.TEUFELSKIND.RIGHT_MASTER_INVERT); |
||
| 267 | rightSlave.setInverted(Robot.bot == Bot.OOF ? Constants.OOF.RIGHT_SLAVE_INVERT : Constants.TEUFELSKIND.RIGHT_SLAVE_INVERT); |
||
| 268 | leftMaster.setInverted(Robot.bot == Bot.OOF ? Constants.OOF.LEFT_MASTER_INVERT : Constants.TEUFELSKIND.LEFT_MASTER_INVERT); |
||
| 269 | leftSlave.setInverted(Robot.bot == Bot.OOF ? Constants.OOF.LEFT_SLAVE_INVERT : Constants.TEUFELSKIND.LEFT_SLAVE_INVERT); |
||
| 270 | } |
||
| 271 | |||
| 272 | |||
| 273 | public static class PID {
|
||
| 274 | Boolean enabled; |
||
| 275 | |||
| 276 | public PID() {
|
||
| 277 | enabled = true; |
||
| 278 | } |
||
| 279 | public static void setPIDF(double p, double i, double d, double f) {
|
||
| 280 | //For future reference: Inverts must be applied individually |
||
| 281 | setPIDF(Robot.SUB_DRIVE.leftMaster, false, p, i, d, f); |
||
| 282 | setPIDF(Robot.SUB_DRIVE.leftSlave, false, p, i, d, f); |
||
| 283 | setPIDF(Robot.SUB_DRIVE.rightMaster, true, p, i, d, f); |
||
| 284 | setPIDF(Robot.SUB_DRIVE.rightSlave, true, p, i, d, f); |
||
| 285 | } |
||
| 286 | |||
| 287 | public static void setPIDF(TalonSRX _talon, Boolean invert, double p, double i, double d, double f) {
|
||
| 288 | /* first choose the sensor */ |
||
| 289 | _talon.configSelectedFeedbackSensor(FeedbackDevice.CTRE_MagEncoder_Relative, |
||
| 290 | 0, Constants.TIMEOUT_PID); |
||
| 291 | _talon.setSensorPhase(true); |
||
| 292 | _talon.setInverted(invert); |
||
| 293 | /* Set relevant frame periods to be at least as fast as periodic rate*/ |
||
| 294 | _talon.setStatusFramePeriod(StatusFrameEnhanced.Status_13_Base_PIDF0, 10, |
||
|
0 ignored issues
–
show
|
|||
| 295 | Constants.TIMEOUT_PID); |
||
| 296 | _talon.setStatusFramePeriod(StatusFrameEnhanced.Status_10_MotionMagic, 10, |
||
|
0 ignored issues
–
show
|
|||
| 297 | Constants.TIMEOUT_PID); |
||
| 298 | /* set the peak and nominal outputs */ |
||
| 299 | _talon.configNominalOutputForward(0, Constants.TIMEOUT_PID); |
||
| 300 | _talon.configNominalOutputReverse(0, Constants.TIMEOUT_PID); |
||
| 301 | _talon.configPeakOutputForward(1, Constants.TIMEOUT_PID); |
||
| 302 | _talon.configPeakOutputReverse(-1, Constants.TIMEOUT_PID); |
||
| 303 | /* set closed loop gains in slot0 - see documentation */ |
||
| 304 | _talon.selectProfileSlot(0, Constants.RIGHT_PID); |
||
| 305 | _talon.config_kP(0, p, Constants.TIMEOUT_PID); |
||
| 306 | _talon.config_kI(0, i, Constants.TIMEOUT_PID); |
||
| 307 | _talon.config_kD(0, d, Constants.TIMEOUT_PID); |
||
| 308 | _talon.config_kF(0, f, Constants.TIMEOUT_PID); |
||
| 309 | /* set acceleration and vcruise velocity - see documentation */ |
||
| 310 | _talon.configMotionCruiseVelocity(15000, Constants.TIMEOUT_PID); |
||
|
0 ignored issues
–
show
|
|||
| 311 | _talon.configMotionAcceleration(6000, Constants.TIMEOUT_PID); |
||
|
0 ignored issues
–
show
|
|||
| 312 | } |
||
| 313 | |||
| 314 | public void zeroEncoders() {
|
||
| 315 | Robot.SUB_DRIVE.leftMaster.setSelectedSensorPosition(0, 0, Constants.TIMEOUT_PID); |
||
| 316 | Robot.SUB_DRIVE.rightMaster.setSelectedSensorPosition(0, 0, Constants.TIMEOUT_PID); |
||
| 317 | Robot.SUB_DRIVE.leftMaster.setIntegralAccumulator(0,0, Constants.TIMEOUT_PID); |
||
| 318 | Robot.SUB_DRIVE.rightMaster.setIntegralAccumulator(0,0, Constants.TIMEOUT_PID); |
||
| 319 | } |
||
| 320 | |||
| 321 | public double getError() {
|
||
| 322 | return (leftify(Robot.SUB_DRIVE.leftMaster.getErrorDerivative(Constants.LEFT_PID)) + rightify(Robot.SUB_DRIVE.rightMaster.getErrorDerivative(Constants.RIGHT_PID))) / 2.0; |
||
|
0 ignored issues
–
show
|
|||
| 323 | } |
||
| 324 | |||
| 325 | public double getRightInches() {
|
||
| 326 | return rightMag2In(Robot.SUB_DRIVE.rightMaster.getSelectedSensorPosition(Constants.RIGHT_PID)); |
||
| 327 | } |
||
| 328 | |||
| 329 | public double getLeftInches() {
|
||
| 330 | return leftMag2In(Robot.SUB_DRIVE.leftMaster.getSelectedSensorPosition(Constants.LEFT_PID)); |
||
| 331 | } |
||
| 332 | |||
| 333 | public void reset() {
|
||
| 334 | Robot.SUB_DRIVE.leftMaster.setSelectedSensorPosition(0, Constants.LEFT_PID, Constants.TIMEOUT_PID); |
||
| 335 | Robot.SUB_DRIVE.rightMaster.setSelectedSensorPosition(0, Constants.RIGHT_PID, Constants.TIMEOUT_PID); |
||
| 336 | } |
||
| 337 | } |
||
| 338 | } |
||
| 339 |
See this CWE advisory on why this is a security issue.