Skip to content

Commit 9f91a97

Browse files
committed
Merge remote-tracking branch 'origin/master' into update-libs
2 parents 7aee712 + 432cd16 commit 9f91a97

4 files changed

Lines changed: 44 additions & 38 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ publishing {
9292
gpr(MavenPublication) {
9393
groupId = 'org.carlmontrobotics'
9494
artifactId = 'lib199'
95-
version = '4.0.0'
95+
version = '4.0.2'
9696

9797
from components.java
9898
}

src/main/java/org/carlmontrobotics/lib199/DummySparkMaxAnswer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.revrobotics.CANSparkMax;
44
import com.revrobotics.RelativeEncoder;
5+
import com.revrobotics.SparkMaxAbsoluteEncoder;
56
import com.revrobotics.SparkMaxAnalogSensor;
67
import com.revrobotics.SparkMaxLimitSwitch;
78
import com.revrobotics.SparkMaxPIDController;
@@ -23,6 +24,8 @@ public class DummySparkMaxAnswer extends REVLibErrorAnswer {
2324
public static final SparkMaxAnalogSensor DUMMY_ANALOG_SENSOR = Mocks.mock(SparkMaxAnalogSensor.class, REVLibErrorAnswer.ANSWER);
2425
public static final SparkMaxLimitSwitch DUMMY_LIMIT_SWITCH = Mocks.mock(SparkMaxLimitSwitch.class, REVLibErrorAnswer.ANSWER);
2526
public static final SparkMaxPIDController DUMMY_PID_CONTROLLER = Mocks.mock(SparkMaxPIDController.class, ANSWER);
27+
public static final SparkMaxAbsoluteEncoder DUMMY_ABSOLUTE_ENCODER = Mocks.mock(SparkMaxAbsoluteEncoder.class, ANSWER);
28+
2629

2730
@Override
2831
public Object answer(InvocationOnMock invocation) throws Throwable {
@@ -41,6 +44,8 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
4144
return IdleMode.kBrake;
4245
} else if(returnType == AccelStrategy.class) {
4346
return AccelStrategy.kTrapezoidal;
47+
} else if(returnType == SparkMaxAbsoluteEncoder.class) {
48+
return DUMMY_ABSOLUTE_ENCODER;
4449
}
4550
return super.answer(invocation);
4651
}

src/main/java/org/carlmontrobotics/lib199/path/SwerveDriveInterface.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import edu.wpi.first.math.trajectory.constraint.SwerveDriveKinematicsConstraint;
2222
import edu.wpi.first.wpilibj2.command.Command;
2323
import edu.wpi.first.wpilibj2.command.CommandBase;
24-
import edu.wpi.first.wpilibj2.command.Subsystem;
2524
import edu.wpi.first.wpilibj2.command.SwerveControllerCommand;
2625

2726
public interface SwerveDriveInterface extends DrivetrainInterface {
@@ -113,22 +112,16 @@ public default Command createPPAutoCommand(PathPlannerTrajectory trajectory, Has
113112
* @return PPSwerveControllerCommand
114113
*/
115114
public default Command createPPAutoCommand(List<PathPlannerTrajectory> trajectory, HashMap<String, Command> eventMap) {
116-
Subsystem[] requirements = eventMap.values().stream().flatMap(command -> command.getRequirements().stream())
117-
.toArray(Subsystem[]::new);
118-
requirements = Arrays.copyOf(requirements, requirements.length + 1);
119-
requirements[requirements.length - 1] = this;
120-
requirements = Arrays.stream(requirements).distinct().toArray(Subsystem[]::new);
121-
final Subsystem[] finalRequirements = requirements; // Make this final so it can be used in the anonymous inner class
122115
PIDController[] pidControllers = Arrays.stream(getPIDConstants()).map(constants -> new PIDController(constants[0], constants[1], constants[2])).toArray(PIDController[]::new);
123116
pidControllers[2].enableContinuousInput(-Math.PI, Math.PI);
124117
// Use SwerveAutoBuilder because required argument for base auto builder "DrivetrainType" is protected
125118
return new SwerveAutoBuilder(this::getPose, this::setPose, null, null, null, null, eventMap, true) {
126119
@Override
127120
public CommandBase followPath(PathPlannerTrajectory trajectory) {
128121
// AutoBuilder will convert this to work with events
129-
return new PPSwerveControllerCommand(trajectory, poseSupplier, getKinematics(), pidControllers[0], pidControllers[1], pidControllers[2], SwerveDriveInterface.this::drive, true, finalRequirements /* This will propagate the requirements to the final command via SequentialCommandGroup */);
122+
return new PPSwerveControllerCommand(trajectory, poseSupplier, getKinematics(), pidControllers[0], pidControllers[1], pidControllers[2], SwerveDriveInterface.this::drive, true, SwerveDriveInterface.this);
130123
};
131-
}.followPathGroupWithEvents(trajectory);
124+
}.fullAuto(trajectory);
132125
}
133126

134127
}

src/main/java/org/carlmontrobotics/lib199/swerve/SwerveModule.java

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public enum ModuleType {FL, FR, BL, BR};
4040
private boolean reversed;
4141
private Timer timer;
4242
private SimpleMotorFeedforward forwardSimpleMotorFF, backwardSimpleMotorFF, turnSimpleMotorFeedforward;
43-
private double lastAngle, maxAchievableTurnVelocityDps, maxAchievableTurnAccelerationMps2, turnToleranceDeg, angleDiff;
43+
private double desiredSpeed, lastAngle, maxAchievableTurnVelocityDps, maxAchievableTurnAccelerationMps2, turnToleranceDeg, angleDiff;
4444

4545
public SwerveModule(SwerveConfig config, ModuleType type, CANSparkMax drive, CANSparkMax turn, CANCoder turnEncoder,
4646
int arrIndex, Supplier<Float> pitchDegSupplier, Supplier<Float> rollDegSupplier) {
@@ -126,23 +126,40 @@ public ModuleType getType() {
126126

127127
private double prevTurnVelocity = 0;
128128
public void periodic() {
129-
double measuredAngleDegs = getModuleAngle();
130-
TrapezoidProfile.State goal = turnPIDController.getGoal();
131-
goal = new TrapezoidProfile.State(goal.position, goal.velocity);
132-
133-
double period = turnPIDController.getPeriod();
134-
double optimalTurnVelocityDps = Math.abs(MathUtil.inputModulus(goal.position-measuredAngleDegs, -180, 180))/period;
135-
setMaxTurnVelocity(Math.min(maxAchievableTurnVelocityDps, optimalTurnVelocityDps));
136-
137-
double turnSpeedCorrectionDps = turnPIDController.calculate(measuredAngleDegs) * turnSimpleMotorFeedforward.maxAchievableVelocity(12,0);
138-
TrapezoidProfile.State state = turnPIDController.getSetpoint();
139-
double turnVolts = turnSimpleMotorFeedforward.calculate(prevTurnVelocity+turnSpeedCorrectionDps, (state.velocity-prevTurnVelocity) / period);
140-
if (!turnPIDController.atGoal()) {
141-
turn.setVoltage(MathUtil.clamp(turnVolts, -12.0, 12.0));
142-
} else {
143-
turn.setVoltage(turnSimpleMotorFeedforward.calculate(goal.velocity));
129+
130+
// Drive Control
131+
{
132+
double actualSpeed = getCurrentSpeed();
133+
double targetVoltage = (actualSpeed >= 0 ? forwardSimpleMotorFF :
134+
backwardSimpleMotorFF).calculate(desiredSpeed, calculateAntiGravitationalA(pitchDegSupplier.get(), rollDegSupplier.get()));//clippedAcceleration);
135+
136+
// Use robot characterization as a simple physical model to account for internal resistance, frcition, etc.
137+
// Add a PID adjustment for error correction (also "drives" the actual speed to the desired speed)
138+
targetVoltage += drivePIDController.calculate(actualSpeed, desiredSpeed);
139+
double appliedVoltage = MathUtil.clamp(targetVoltage, -12, 12);
140+
drive.setVoltage(appliedVoltage);
141+
}
142+
143+
// Turn Control
144+
{
145+
double measuredAngleDegs = getModuleAngle();
146+
TrapezoidProfile.State goal = turnPIDController.getGoal();
147+
goal = new TrapezoidProfile.State(goal.position, goal.velocity);
148+
149+
double period = turnPIDController.getPeriod();
150+
double optimalTurnVelocityDps = Math.abs(MathUtil.inputModulus(goal.position-measuredAngleDegs, -180, 180))/period;
151+
setMaxTurnVelocity(Math.min(maxAchievableTurnVelocityDps, optimalTurnVelocityDps));
152+
153+
double turnSpeedCorrectionDps = turnPIDController.calculate(measuredAngleDegs) * turnSimpleMotorFeedforward.maxAchievableVelocity(12,0);
154+
TrapezoidProfile.State state = turnPIDController.getSetpoint();
155+
double turnVolts = turnSimpleMotorFeedforward.calculate(prevTurnVelocity+turnSpeedCorrectionDps, (state.velocity-prevTurnVelocity) / period);
156+
if (!turnPIDController.atGoal()) {
157+
turn.setVoltage(MathUtil.clamp(turnVolts, -12.0, 12.0));
158+
} else {
159+
turn.setVoltage(turnSimpleMotorFeedforward.calculate(goal.velocity));
160+
}
161+
prevTurnVelocity = state.velocity;
144162
}
145-
prevTurnVelocity = state.velocity;
146163
}
147164

148165
/**
@@ -177,22 +194,13 @@ private double calculateAntiGravitationalA(Float gyroPitchDeg, Float gyroRollDeg
177194
SmartDashboard.putNumber("AntiGravitational accelration", antiGravitationalA);
178195
return antiGravitationalA;
179196
}
197+
180198
/**
181199
* Sets the speed for the drive motor controller.
182200
* @param speedMps The desired speed in meters per second.
183201
*/
184202
private void setSpeed(double speedMps) {
185-
// Compute desired and actual speeds in m/s
186-
double desiredSpeed = speedMps * driveModifier;
187-
double actualSpeed = getCurrentSpeed();
188-
double targetVoltage = (actualSpeed >= 0 ? forwardSimpleMotorFF :
189-
backwardSimpleMotorFF).calculate(desiredSpeed, calculateAntiGravitationalA(pitchDegSupplier.get(), rollDegSupplier.get()));//clippedAcceleration);
190-
191-
// Use robot characterization as a simple physical model to account for internal resistance, frcition, etc.
192-
// Add a PID adjustment for error correction (also "drives" the actual speed to the desired speed)
193-
targetVoltage += drivePIDController.calculate(actualSpeed, desiredSpeed);
194-
double appliedVoltage = MathUtil.clamp(targetVoltage, -12, 12);
195-
drive.setVoltage(appliedVoltage);
203+
desiredSpeed = speedMps * driveModifier;
196204
}
197205

198206
/**

0 commit comments

Comments
 (0)