3535 */
3636public class TankDrive implements Requirable {
3737
38+ public static enum CheesyAlgorithm {
39+ SIMPLE , INERTIA
40+ }
41+
3842 public static final double DEFAULT_MINIMUM_SPEED = 0.02 ;
3943 public static final double DEFAULT_MAXIMUM_SPEED = 1.0 ;
4044 public static final DoubleToDoubleFunction DEFAULT_SPEED_LIMITER = Values .symmetricLimiter (DEFAULT_MINIMUM_SPEED ,
@@ -43,6 +47,7 @@ public class TankDrive implements Requirable {
4347 private static final double SENSITIVITY_HIGH = 0.75 ;
4448 private static final double SENSITIVITY_LOW = 0.75 ;
4549 private static final double HALF_PI = Math .PI / 2.0 ;
50+ private static final double SENSITIVITY_TURN = 1.0 ;
4651
4752 private final Motor left ;
4853 private final Motor right ;
@@ -54,7 +59,7 @@ public class TankDrive implements Requirable {
5459
5560 /**
5661 * Creates a new DriveSystem subsystem that uses the supplied drive train and no shifter. The voltage send to the drive
57- * train is limited to [-1.0,1.0].
62+ * train is limited to [-1.0,1.0] with the exception of the (-0.02,0.02) deadband around the zero point .
5863 *
5964 * @param left the left motor on the drive train for the robot; may not be null
6065 * @param right the right motor on the drive train for the robot; may not be null
@@ -65,7 +70,7 @@ public TankDrive(Motor left, Motor right) {
6570
6671 /**
6772 * Creates a new DriveSystem subsystem that uses the supplied drive train and optional shifter. The voltage send to the
68- * drive train is limited to [-1.0,1.0].
73+ * drive train is limited to [-1.0,1.0] with the exception of the (-0.02,0.02) deadband around the zero point .
6974 *
7075 * @param left the left motor on the drive train for the robot; may not be null
7176 * @param right the right motor on the drive train for the robot; may not be null
@@ -83,7 +88,7 @@ public TankDrive(Motor left, Motor right, Relay shifter) {
8388 * @param right the right motor on the drive train for the robot; may not be null
8489 * @param shifter the optional shifter used to put the transmission into high gear; may be null
8590 * @param speedLimiter the function that limits the speed sent to the drive train; if null, then a default clamping function
86- * is used to limit to the range [-1.0,1.0]
91+ * is used to limit to the range [-1.0,1.0] with the exception of the (-0.02,0.02) deadband around the zero point
8792 */
8893 public TankDrive (Motor left , Motor right , Relay shifter , DoubleToDoubleFunction speedLimiter ) {
8994 this .left = left ;
@@ -231,6 +236,66 @@ private static double dampen(double wheel, double wheelNonLinearity) {
231236 return Math .sin (factor * wheel ) / Math .sin (factor );
232237 }
233238
239+ /**
240+ * Provide "cheesy drive" steering using a steering wheel and throttle. This function lets you directly provide joystick
241+ * values from any source.
242+ * <p>
243+ * "Cheesy Drive" simply means that the "turning" stick controls the curvature of the robot's path rather than its rate of
244+ * heading change. This helps make the robot more controllable at high speeds. Also handles the robot's quick turn
245+ * functionality - "quick turn" overrides constant-curvature turning for turn-in-place maneuvers.
246+ * <p>
247+ * This is equivalent to calling {@code cheesy(throttle, wheel, isQuickTurn, CheesyAlgorithm.SIMPLE)}.
248+ *
249+ * @param throttle the value of the throttle, which is generally in the range -1 to 1 inclusive but limited by the speed
250+ * limiter provided in the constructor
251+ * @param wheel the value of the steering wheel, which is generally in the range -1 to 1 inclusive but limited by the speed
252+ * limiter provided in the constructor and where negative values turn right and positive values turn left
253+ * @param isQuickTurn true if the quick-turn button is pressed
254+ * @see <a href="https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/CheesyDriveHelper.java">Team
255+ * 254 Cheesy Drive logic from 2016</a>
256+ */
257+ public void cheesy (double throttle , double wheel , boolean isQuickTurn ) {
258+ cheesy2016 (throttle , wheel , isQuickTurn );
259+ }
260+
261+ /**
262+ * Provide "cheesy drive" steering using a steering wheel and throttle. This function lets you directly provide joystick
263+ * values from any source.
264+ * <p>
265+ * "Cheesy Drive" simply means that the "turning" stick controls the curvature of the robot's path rather than its rate of
266+ * heading change. This helps make the robot more controllable at high speeds. Also handles the robot's quick turn
267+ * functionality - "quick turn" overrides constant-curvature turning for turn-in-place maneuvers.
268+ * <p>
269+ * This method supports two different algorithms for cheesy drive:
270+ * <ul>
271+ * <li><i>simple<i> - an improved and simplified algorithm from
272+ * <a href="https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/CheesyDriveHelper.java">Team 254
273+ * Cheesy Drive logic from 2016</a>; and</li>
274+ * <li><i>inertia<i> - an earlier algorithm that uses inertia terms to non-linearly smooth the outputs, from
275+ * <a href="https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/CheesyDriveHelper.java">Team 254
276+ * Cheesy Drive logic from 2014</a></li>
277+ * </ul>
278+ *
279+ * @param throttle the value of the throttle, which is generally in the range -1 to 1 inclusive but limited by the speed
280+ * limiter provided in the constructor
281+ * @param wheel the value of the steering wheel, which is generally in the range -1 to 1 inclusive but limited by the speed
282+ * limiter provided in the constructor and where negative values turn right and positive values turn left
283+ * @param isQuickTurn true if the quick-turn button is pressed
284+ * @param algorithm the algorithm to use; may not be null
285+ * @see <a href="https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/CheesyDriveHelper.java">Team
286+ * 254 Cheesy Drive logic from 2016</a>
287+ */
288+ public void cheesy (double throttle , double wheel , boolean isQuickTurn , CheesyAlgorithm algorithm ) {
289+ switch (algorithm ) {
290+ case INERTIA :
291+ cheesy2014 (throttle , wheel , isQuickTurn );
292+ break ;
293+ case SIMPLE :
294+ cheesy2016 (throttle , wheel , isQuickTurn );
295+ break ;
296+ }
297+ }
298+
234299 /**
235300 * Provide "cheesy drive" steering using a steering wheel and throttle. This function lets you directly provide joystick
236301 * values from any source.
@@ -240,9 +305,9 @@ private static double dampen(double wheel, double wheelNonLinearity) {
240305 * left.
241306 * @param isQuickTurn true if the quick-turn button is pressed
242307 * @see <a href="https://github.com/Team254/FRC-2014/blob/master/src/com/team254/frc2014/CheesyDriveHelper.java">Team 254
243- * Cheesy Drive logic</a>
308+ * Cheesy Drive logic from 2014 </a>
244309 */
245- public void cheesy (double throttle , double wheel , boolean isQuickTurn ) {
310+ private void cheesy2014 (double throttle , double wheel , boolean isQuickTurn ) {
246311
247312 wheel = speedLimiter .applyAsDouble (wheel );
248313 throttle = speedLimiter .applyAsDouble (throttle );
@@ -348,4 +413,65 @@ public void cheesy(double throttle, double wheel, boolean isQuickTurn) {
348413 right .setSpeed (rightPwm );
349414 }
350415
416+ /**
417+ * Provide a simpler "cheesy drive" steering using a steering wheel and throttle. This function lets you directly provide
418+ * joystick values from any source.
419+ * <p>
420+ * "Cheesy Drive" simply means that the "turning" stick controls the curvature of the robot's path rather than its rate of
421+ * heading change. This helps make the robot more controllable at high speeds. Also handles the robot's quick turn
422+ * functionality - "quick turn" overrides constant-curvature turning for turn-in-place maneuvers.
423+ *
424+ * @param throttle the value of the throttle, which is generally in the range -1 to 1 inclusive but limited by the speed
425+ * limiter provided in the constructor
426+ * @param wheel the value of the steering wheel, which is generally in the range -1 to 1 inclusive but limited by the speed
427+ * limiter provided in the constructor and where negative values turn right and positive values turn left
428+ * @param isQuickTurn true if the quick-turn button is pressed
429+ * @see <a href="https://github.com/Team254/FRC-2016-Public/blob/master/src/com/team254/frc2016/CheesyDriveHelper.java">Team
430+ * 254 Cheesy Drive logic from 2016</a>
431+ */
432+ private void cheesy2016 (double throttle , double wheel , boolean isQuickTurn ) {
433+ wheel = speedLimiter .applyAsDouble (wheel );
434+ throttle = speedLimiter .applyAsDouble (throttle );
435+
436+ double overPower ;
437+ double angularPower ;
438+
439+ if (isQuickTurn ) {
440+ if (Math .abs (throttle ) < DEFAULT_MINIMUM_SPEED ) {
441+ double alpha = 0.1 ;
442+ quickStopAccumulator = (1 - alpha ) * quickStopAccumulator + alpha * Values .symmetricLimit (0.0 , wheel , 1.0 ) * 2 ;
443+ }
444+ overPower = 1.0 ;
445+ angularPower = wheel ;
446+ } else {
447+ overPower = 0.0 ;
448+ angularPower = Math .abs (throttle ) * wheel * SENSITIVITY_TURN - quickStopAccumulator ;
449+ if (quickStopAccumulator > 1 ) {
450+ quickStopAccumulator -= 1 ;
451+ } else if (quickStopAccumulator < -1 ) {
452+ quickStopAccumulator += 1 ;
453+ } else {
454+ quickStopAccumulator = 0.0 ;
455+ }
456+ }
457+
458+ double rightPwm = throttle - angularPower ;
459+ double leftPwm = throttle + angularPower ;
460+ if (leftPwm > 1.0 ) {
461+ rightPwm -= overPower * (leftPwm - 1.0 );
462+ leftPwm = 1.0 ;
463+ } else if (rightPwm > 1.0 ) {
464+ leftPwm -= overPower * (rightPwm - 1.0 );
465+ rightPwm = 1.0 ;
466+ } else if (leftPwm < -1.0 ) {
467+ rightPwm += overPower * (-1.0 - leftPwm );
468+ leftPwm = -1.0 ;
469+ } else if (rightPwm < -1.0 ) {
470+ leftPwm += overPower * (-1.0 - rightPwm );
471+ rightPwm = -1.0 ;
472+ }
473+ left .setSpeed (leftPwm );
474+ right .setSpeed (rightPwm );
475+ }
476+
351477}
0 commit comments