001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */ 003/* Open Source Software - may be modified and shared by FRC teams. The code */ 004/* must be accompanied by the FIRST BSD license file in the root directory of */ 005/* the project. */ 006/*----------------------------------------------------------------------------*/ 007 008package edu.wpi.first.wpilibj.drive; 009 010import edu.wpi.first.wpilibj.MotorSafety; 011import edu.wpi.first.wpilibj.MotorSafetyHelper; 012import edu.wpi.first.wpilibj.SendableBase; 013 014/** 015 * Common base class for drive platforms. 016 */ 017public abstract class RobotDriveBase extends SendableBase implements MotorSafety { 018 public static final double kDefaultDeadband = 0.02; 019 public static final double kDefaultMaxOutput = 1.0; 020 021 protected double m_deadband = kDefaultDeadband; 022 protected double m_maxOutput = kDefaultMaxOutput; 023 protected MotorSafetyHelper m_safetyHelper = new MotorSafetyHelper(this); 024 025 /** 026 * The location of a motor on the robot for the purpose of driving. 027 */ 028 public enum MotorType { 029 kFrontLeft(0), kFrontRight(1), kRearLeft(2), kRearRight(3), kLeft(0), 030 kRight(1), kBack(2); 031 032 @SuppressWarnings("MemberName") 033 public final int value; 034 035 MotorType(int value) { 036 this.value = value; 037 } 038 } 039 040 public RobotDriveBase() { 041 m_safetyHelper.setSafetyEnabled(true); 042 setName("RobotDriveBase"); 043 } 044 045 /** 046 * Change the default value for deadband scaling. The default value is 047 * {@value #kDefaultDeadband}. Values smaller then the deadband are set to 0, while values 048 * larger then the deadband are scaled from 0.0 to 1.0. See {@link #applyDeadband}. 049 * 050 * @param deadband The deadband to set. 051 */ 052 public void setDeadband(double deadband) { 053 m_deadband = deadband; 054 } 055 056 /** 057 * Configure the scaling factor for using drive methods with motor controllers in a mode other 058 * than PercentVbus or to limit the maximum output. 059 * 060 * <p>The default value is {@value #kDefaultMaxOutput}. 061 * 062 * @param maxOutput Multiplied with the output percentage computed by the drive functions. 063 */ 064 public void setMaxOutput(double maxOutput) { 065 m_maxOutput = maxOutput; 066 } 067 068 @Override 069 public void setExpiration(double timeout) { 070 m_safetyHelper.setExpiration(timeout); 071 } 072 073 @Override 074 public double getExpiration() { 075 return m_safetyHelper.getExpiration(); 076 } 077 078 @Override 079 public boolean isAlive() { 080 return m_safetyHelper.isAlive(); 081 } 082 083 @Override 084 public abstract void stopMotor(); 085 086 @Override 087 public boolean isSafetyEnabled() { 088 return m_safetyHelper.isSafetyEnabled(); 089 } 090 091 @Override 092 public void setSafetyEnabled(boolean enabled) { 093 m_safetyHelper.setSafetyEnabled(enabled); 094 } 095 096 @Override 097 public abstract String getDescription(); 098 099 /** 100 * Limit motor values to the -1.0 to +1.0 range. 101 */ 102 protected double limit(double value) { 103 if (value > 1.0) { 104 return 1.0; 105 } 106 if (value < -1.0) { 107 return -1.0; 108 } 109 return value; 110 } 111 112 /** 113 * Returns 0.0 if the given value is within the specified range around zero. The remaining range 114 * between the deadband and 1.0 is scaled from 0.0 to 1.0. 115 * 116 * @param value value to clip 117 * @param deadband range around zero 118 */ 119 protected double applyDeadband(double value, double deadband) { 120 if (Math.abs(value) > deadband) { 121 if (value > 0.0) { 122 return (value - deadband) / (1.0 - deadband); 123 } else { 124 return (value + deadband) / (1.0 - deadband); 125 } 126 } else { 127 return 0.0; 128 } 129 } 130 131 /** 132 * Normalize all wheel speeds if the magnitude of any wheel is greater than 1.0. 133 */ 134 protected void normalize(double[] wheelSpeeds) { 135 double maxMagnitude = Math.abs(wheelSpeeds[0]); 136 for (int i = 1; i < wheelSpeeds.length; i++) { 137 double temp = Math.abs(wheelSpeeds[i]); 138 if (maxMagnitude < temp) { 139 maxMagnitude = temp; 140 } 141 } 142 if (maxMagnitude > 1.0) { 143 for (int i = 0; i < wheelSpeeds.length; i++) { 144 wheelSpeeds[i] = wheelSpeeds[i] / maxMagnitude; 145 } 146 } 147 } 148}