-
Notifications
You must be signed in to change notification settings - Fork 35
/
CheesyDriveHelper.java
150 lines (128 loc) · 5.91 KB
/
CheesyDriveHelper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.team254.lib.util;
import com.team254.frc2019.subsystems.Drive;
/**
* Helper class to implement "Cheesy Drive". "Cheesy Drive" simply means that the "turning" stick controls the curvature
* of the robot's path rather than its rate of heading change. This helps make the robot more controllable at high
* speeds. Also handles the robot's quick turn functionality - "quick turn" overrides constant-curvature turning for
* turn-in-place maneuvers.
*/
public class CheesyDriveHelper {
private static final double kThrottleDeadband = 0.035;
private static final double kWheelDeadband = 0.02;
// These factor determine how fast the wheel traverses the "non linear" sine curve.
private static final double kHighWheelNonLinearity = 0.01;
private static final double kLowWheelNonLinearity = 0.5;
private static final double kHighNegInertiaScalar = 0.0;
private static final double kLowNegInertiaThreshold = 0.65;
private static final double kLowNegInertiaTurnScalar = 3.0;
private static final double kLowNegInertiaCloseScalar = 3.0;
private static final double kLowNegInertiaFarScalar = 4.0;
private static final double kHighSensitivity = 0.6;
private static final double kLowSensitiity = 0.625;
private static final double kWheelQuckTurnScalar = .65;
private static final double kQuickStopDeadband = 0.5;
private static final double kQuickStopWeight = 0.125;
private static final double kQuickStopScalar = 2.8;
private double mOldWheel = 0.0;
private double mQuickStopAccumlator = 0.0;
private double mNegInertiaAccumlator = 0.0;
public DriveSignal cheesyDrive(double throttle, double wheel, boolean isQuickTurn,
boolean isHighGear) {
wheel = handleDeadband(wheel, kWheelDeadband);
throttle = handleDeadband(throttle, kThrottleDeadband);
double negInertia = wheel - mOldWheel;
mOldWheel = wheel;
double wheelNonLinearity;
if (isHighGear) {
wheelNonLinearity = kHighWheelNonLinearity;
final double denominator = Math.sin(Math.PI / 2.0 * wheelNonLinearity);
// Apply a sin function that's scaled to make it feel better.
wheel = Math.sin(Math.PI / 2.0 * wheelNonLinearity * wheel) / denominator;
wheel = Math.sin(Math.PI / 2.0 * wheelNonLinearity * wheel) / denominator;
} else {
wheelNonLinearity = kLowWheelNonLinearity;
final double denominator = Math.sin(Math.PI / 2.0 * wheelNonLinearity);
// Apply a sin function that's scaled to make it feel better.
wheel = Math.sin(Math.PI / 2.0 * wheelNonLinearity * wheel) / denominator;
wheel = Math.sin(Math.PI / 2.0 * wheelNonLinearity * wheel) / denominator;
wheel = Math.sin(Math.PI / 2.0 * wheelNonLinearity * wheel) / denominator;
}
double leftPwm, rightPwm, overPower;
double sensitivity;
double angularPower;
double linearPower;
// Negative inertia!
double negInertiaScalar;
if (isHighGear) {
negInertiaScalar = kHighNegInertiaScalar;
sensitivity = kHighSensitivity;
} else {
if (wheel * negInertia > 0) {
// If we are moving away from 0.0, aka, trying to get more wheel.
negInertiaScalar = kLowNegInertiaTurnScalar;
} else {
// Otherwise, we are attempting to go back to 0.0.
if (Math.abs(wheel) > kLowNegInertiaThreshold) {
negInertiaScalar = kLowNegInertiaFarScalar;
} else {
negInertiaScalar = kLowNegInertiaCloseScalar;
}
}
sensitivity = kLowSensitiity;
}
double negInertiaPower = negInertia * negInertiaScalar;
mNegInertiaAccumlator += negInertiaPower;
wheel = wheel + mNegInertiaAccumlator;
if (mNegInertiaAccumlator > 1) {
mNegInertiaAccumlator -= 1;
} else if (mNegInertiaAccumlator < -1) {
mNegInertiaAccumlator += 1;
} else {
mNegInertiaAccumlator = 0;
}
linearPower = throttle;
// Quickturn!
if (isQuickTurn) {
if (Math.abs(linearPower) < kQuickStopDeadband) {
double alpha = kQuickStopWeight;
mQuickStopAccumlator = (1 - alpha) * mQuickStopAccumlator
+ alpha * Util.limit(wheel, 1.0) * kQuickStopScalar;
}
overPower = 1.0;
angularPower = wheel * kWheelQuckTurnScalar;
} else {
overPower = 0.0;
angularPower = Math.abs(throttle) * wheel * sensitivity - mQuickStopAccumlator;
if (mQuickStopAccumlator > 1) {
mQuickStopAccumlator -= 1;
} else if (mQuickStopAccumlator < -1) {
mQuickStopAccumlator += 1;
} else {
mQuickStopAccumlator = 0.0;
}
}
rightPwm = leftPwm = linearPower;
leftPwm += angularPower;
rightPwm -= angularPower;
if (leftPwm > 1.0) {
rightPwm -= overPower * (leftPwm - 1.0);
leftPwm = 1.0;
} else if (rightPwm > 1.0) {
leftPwm -= overPower * (rightPwm - 1.0);
rightPwm = 1.0;
} else if (leftPwm < -1.0) {
rightPwm += overPower * (-1.0 - leftPwm);
leftPwm = -1.0;
} else if (rightPwm < -1.0) {
leftPwm += overPower * (-1.0 - rightPwm);
rightPwm = -1.0;
}
return new DriveSignal(leftPwm, rightPwm);
}
public DriveSignal cheesyDrive(double throttle, double wheel, boolean isQuickTurn) {
return cheesyDrive(throttle, wheel, isQuickTurn, Drive.getInstance().isHighGear());
}
public double handleDeadband(double val, double deadband) {
return (Math.abs(val) > Math.abs(deadband)) ? val : 0.0;
}
}