Skip to content

Commit 7b81fcb

Browse files
committed
Issue 56 - Improved Cheesy drive logic
Added a second and simpler algorithm for cheesy drive based on Team 254’s 2016 robot, and change the existing `cheesy` method to use this algorithm. However, the previous logic is still available via a new overloaded method that accepts the algorithm enumeration as the fourth parameter.
1 parent c827eb9 commit 7b81fcb

File tree

1 file changed

+131
-5
lines changed

1 file changed

+131
-5
lines changed

strongback/src/org/strongback/drive/TankDrive.java

Lines changed: 131 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
*/
3636
public 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

Comments
 (0)