Skip to content

Commit

Permalink
Merge branch 'selfridge-changes' into dropping
Browse files Browse the repository at this point in the history
  • Loading branch information
faeqk committed Jun 18, 2024
2 parents 1c11f16 + 0fc70c6 commit 67111cf
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 20 deletions.
51 changes: 38 additions & 13 deletions src/main/java/com/team1701/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.team1701.robot.Configuration.Mode;
import com.team1701.robot.commands.AutonomousCommands;
import com.team1701.robot.commands.DriveCommands;
import com.team1701.robot.commands.DriveWithAssist;
import com.team1701.robot.commands.IntakeCommands;
import com.team1701.robot.commands.ShootCommands;
import com.team1701.robot.controls.RumbleController;
Expand Down Expand Up @@ -100,12 +101,12 @@ public RobotContainer() {
TalonFxMotorFactory.createDriveMotorIOTalonFxFoc(10),
TalonFxMotorFactory.createSteerMotorIOTalonFxFoc(11),
new EncoderIOAnalog(0),
Rotation2d.fromRadians(-2.262)),
Rotation2d.fromRadians(-2.237)),
new SwerveModuleIO(
TalonFxMotorFactory.createDriveMotorIOTalonFxFoc(12),
TalonFxMotorFactory.createSteerMotorIOTalonFxFoc(13),
new EncoderIOAnalog(1),
Rotation2d.fromRadians(-3.069)),
Rotation2d.fromRadians(-3.869)),
new SwerveModuleIO(
TalonFxMotorFactory.createDriveMotorIOTalonFxFoc(14),
TalonFxMotorFactory.createSteerMotorIOTalonFxFoc(15),
Expand Down Expand Up @@ -343,15 +344,36 @@ private void setupControllerBindings() {

/* DEFAULT COMMANDS */

mDrive.setDefaultCommand(driveWithJoysticks(
mDrive,
mDrive::getFieldRelativeHeading,
() -> -mDriverController.getLeftY(),
() -> -mDriverController.getLeftX(),
() -> -mDriverController.getRightX(),
() -> mDriverController.getHID().getRightBumper()
? Constants.Drive.kSlowKinematicLimits
: Constants.Drive.kFastKinematicLimits));
mDrive.setDefaultCommand(Commands.either(
new DriveWithAssist(
mDrive,
mRobotState,
() -> -mDriverController.getLeftY(),
() -> -mDriverController.getLeftX(),
() -> -mDriverController.getRightX(),
() -> mDriverController.getHID().getRightBumper()
? Constants.Drive.kSlowKinematicLimits
: Constants.Drive.kFastKinematicLimits),
DriveCommands.driveWithJoysticks(
mDrive,
mDrive::getFieldRelativeHeading,
() -> -mDriverController.getLeftY(),
() -> -mDriverController.getLeftX(),
() -> -mDriverController.getRightX(),
() -> mDriverController.getHID().getRightBumper()
? Constants.Drive.kSlowKinematicLimits
: Constants.Drive.kFastKinematicLimits),
mDrive::useDriveAssist));

// mDrive.setDefaultCommand(driveWithJoysticks(
// mDrive,
// mDrive::getFieldRelativeHeading,
// () -> -mDriverController.getLeftY(),
// () -> -mDriverController.getLeftX(),
// () -> -mDriverController.getRightX(),
// () -> mDriverController.getHID().getRightBumper()
// ? Constants.Drive.kSlowKinematicLimits
// : Constants.Drive.kFastKinematicLimits));

mIndexer.setDefaultCommand(IntakeCommands.idleIndexer(mIndexer));

Expand Down Expand Up @@ -482,6 +504,9 @@ private void setupControllerBindings() {
var setAmpModeCommand = runOnce(() -> mRobotState.setScoringMode(ScoringMode.AMP))
.ignoringDisable(true)
.withName("SetAmpScoringMode");
var setDriveAssist = runOnce(() -> mDrive.toggleDriveAssist(), mDrive)
.ignoringDisable(true)
.withName("SetDriveAssist");
var setClimbModeCommand = runOnce(() -> mRobotState.setScoringMode(ScoringMode.CLIMB))
.ignoringDisable(true)
.withName("SetClimbScoringMode");
Expand Down Expand Up @@ -520,7 +545,7 @@ private void setupControllerBindings() {
mStreamDeck.configureButton(config -> config.add(
StreamDeckButton.kSpeakerModeButton, () -> mRobotState.getScoringMode() == ScoringMode.SPEAKER)
.add(StreamDeckButton.kAmpModeButton, () -> mRobotState.getScoringMode() == ScoringMode.AMP)
.add(StreamDeckButton.kClimbModeButton, () -> mRobotState.getScoringMode() == ScoringMode.CLIMB)
.add(StreamDeckButton.kDriveAssistButton, mDrive::useDriveAssist)
.add(StreamDeckButton.kStopIntakeButton, stopIntakingCommand::isScheduled)
.add(StreamDeckButton.kRejectButton, rejectCommand::isScheduled)
.add(StreamDeckButton.kForwardButton, forwardCommand::isScheduled)
Expand Down Expand Up @@ -551,7 +576,7 @@ private void setupControllerBindings() {

mStreamDeck.button(StreamDeckButton.kSpeakerModeButton).onTrue(setSpeakerModeCommand);
mStreamDeck.button(StreamDeckButton.kAmpModeButton).onTrue(setAmpModeCommand);
mStreamDeck.button(StreamDeckButton.kClimbModeButton).onTrue(setClimbModeCommand);
mStreamDeck.button(StreamDeckButton.kDriveAssistButton).onTrue(setDriveAssist);

mStreamDeck
.button(StreamDeckButton.kRaiseShooterButton)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static Command driveWithJoysticks(
.withName("DriveWithJoysticks");
}

private static Translation2d calculateDriveWithJoysticksVelocities(
public static Translation2d calculateDriveWithJoysticksVelocities(
double throttle, double strafe, Rotation2d heading, double maxVelocity) {
var translationSign = Configuration.isBlueAlliance() ? 1.0 : -1.0;
var magnitude = Math.hypot(throttle, strafe);
Expand Down
190 changes: 190 additions & 0 deletions src/main/java/com/team1701/robot/commands/DriveWithAssist.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package com.team1701.robot.commands;

import java.util.function.DoubleSupplier;
import java.util.function.Supplier;

import com.team1701.lib.swerve.SwerveSetpointGenerator.KinematicLimits;
import com.team1701.lib.util.GeometryUtil;
import com.team1701.lib.util.Util;
import com.team1701.lib.util.tuning.LoggedTunableNumber;
import com.team1701.lib.util.tuning.LoggedTunableValue;
import com.team1701.robot.Constants;
import com.team1701.robot.states.RobotState;
import com.team1701.robot.subsystems.drive.Drive;
import edu.wpi.first.math.MathUtil;
import edu.wpi.first.math.controller.PIDController;
import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.geometry.Translation2d;
import edu.wpi.first.math.kinematics.ChassisSpeeds;
import edu.wpi.first.math.trajectory.TrapezoidProfile;
import edu.wpi.first.wpilibj2.command.Command;
import org.littletonrobotics.junction.Logger;

public class DriveWithAssist extends Command {
private static final String kLoggingPrefix = "Command/DriveWithAimAssist/";
private static final double kModuleRadius = Constants.Drive.kModuleRadius;
private static final TrapezoidProfile.State kZeroState = new TrapezoidProfile.State(0.0, 0.0);

private static final LoggedTunableNumber kMaxAngularVelocity = new LoggedTunableNumber(
kLoggingPrefix + "MaxAngularVelocity",
Constants.Drive.kFastKinematicLimits.maxDriveVelocity() / kModuleRadius);
private static final LoggedTunableNumber kMaxAngularAcceleration = new LoggedTunableNumber(
kLoggingPrefix + "MaxAngularAcceleration",
Constants.Drive.kFastKinematicLimits.maxDriveAcceleration() / kModuleRadius);

private static final LoggedTunableNumber kLoopsLatency =
new LoggedTunableNumber(kLoggingPrefix + "LoopsLatency", 2.0);
private static final LoggedTunableNumber kRotationKp = new LoggedTunableNumber(kLoggingPrefix + "RotationKp", 5.0);
private static final LoggedTunableNumber kRotationKi = new LoggedTunableNumber(kLoggingPrefix + "RotationKi", 0.0);
private static final LoggedTunableNumber kRotationKd = new LoggedTunableNumber(kLoggingPrefix + "RotationKd", 0.0);

private final Drive mDrive;
private final RobotState mRobotState;
private final DoubleSupplier mThrottleSupplier;
private final DoubleSupplier mStrafeSupplier;
private final DoubleSupplier mRotationSupplier;
private final Supplier<KinematicLimits> mKinematicLimits;
private final PIDController mRotationController;

private TrapezoidProfile mRotationProfile;
private TrapezoidProfile.State mRotationState = kZeroState;

public DriveWithAssist(
Drive drive,
RobotState robotState,
DoubleSupplier throttleSupplier,
DoubleSupplier strafeSupplier,
DoubleSupplier rotationSupplier,
Supplier<KinematicLimits> kinematicLimits) {
mDrive = drive;
mRobotState = robotState;
mThrottleSupplier = throttleSupplier;
mStrafeSupplier = strafeSupplier;
mRotationSupplier = rotationSupplier;
mKinematicLimits = kinematicLimits;
mRotationController = new PIDController(
kRotationKp.get(), kRotationKi.get(), kRotationKd.get(), Constants.kLoopPeriodSeconds);
mRotationController.enableContinuousInput(-Math.PI, Math.PI);
mRotationProfile = new TrapezoidProfile(new TrapezoidProfile.Constraints(
Math.min(kMaxAngularVelocity.get(), mKinematicLimits.get().maxDriveVelocity() / kModuleRadius),
Math.min(
kMaxAngularAcceleration.get(), mKinematicLimits.get().maxDriveAcceleration() / kModuleRadius)));

addRequirements(mDrive);
}

@Override
public void initialize() {
mDrive.setKinematicLimits(mKinematicLimits.get());

mRotationController.reset();

var fieldRelativeChassisSpeeds = mRobotState.getFieldRelativeSpeeds();
var detectedNoteHeading = mRobotState.getHeadingToDetectedNoteForPickup();
var headingError = detectedNoteHeading.isEmpty()
? GeometryUtil.kRotationIdentity
: mRobotState.getHeadingToDetectedNoteForPickup().get().minus(mRobotState.getHeading());
mRotationState = new TrapezoidProfile.State(
MathUtil.angleModulus(headingError.getRadians()), fieldRelativeChassisSpeeds.omegaRadiansPerSecond);

LoggedTunableValue.ifChanged(
hashCode(),
() -> {
mRotationProfile = new TrapezoidProfile(new TrapezoidProfile.Constraints(
Math.min(
kMaxAngularVelocity.get(),
mKinematicLimits.get().maxDriveVelocity() / kModuleRadius),
Math.min(
kMaxAngularAcceleration.get(),
mKinematicLimits.get().maxDriveAcceleration() / kModuleRadius)));
mRotationController.setPID(kRotationKp.get(), kRotationKi.get(), kRotationKd.get());
},
kMaxAngularVelocity,
kMaxAngularAcceleration,
kRotationKp,
kRotationKi,
kRotationKd);
}

@Override
public void execute() {
mDrive.setKinematicLimits(mKinematicLimits.get());
var currentPose = mRobotState.getPose2d();
var endTranslation = new Translation2d(
currentPose.getX()
+ mThrottleSupplier.getAsDouble() * Constants.kLoopPeriodSeconds * kLoopsLatency.get(),
currentPose.getY()
+ mStrafeSupplier.getAsDouble() * Constants.kLoopPeriodSeconds * kLoopsLatency.get());
var detectedNoteHeading = mRobotState.getHeadingToDetectedNoteForPickup();
var targetHeading = detectedNoteHeading.isEmpty()
? mRobotState.getHeading()
: detectedNoteHeading.get().plus(GeometryUtil.kRotationPi);
var headingError = detectedNoteHeading.isEmpty()
? GeometryUtil.kRotationIdentity
: targetHeading.minus(mRobotState.getHeading());
var headingTolerance = Rotation2d.fromRadians(0.03);
var translationVelocities = DriveCommands.calculateDriveWithJoysticksVelocities(
mThrottleSupplier.getAsDouble(),
mStrafeSupplier.getAsDouble(),
mDrive.getFieldRelativeHeading(),
mKinematicLimits.get().maxDriveVelocity());
var rotation = MathUtil.applyDeadband(mRotationSupplier.getAsDouble(), Constants.Controls.kDriverDeadband);
var rotationRadiansPerSecond = Math.copySign(rotation * rotation, rotation)
* mKinematicLimits.get().maxDriveVelocity()
/ Constants.Drive.kModuleRadius;
var toleranceDegrees = detectedNoteHeading.isEmpty()
? 0.0
: (180)
/ Math.pow(
Math.abs(mRobotState
.getDistanceToDetectedNoteForPickup()
.getAsDouble()),
2);

var fieldRelativeVelocityHeading =
translationVelocities.rotateBy(mRobotState.getHeading()).getAngle();

Logger.recordOutput(kLoggingPrefix + "ToleranceDegrees", toleranceDegrees);
Logger.recordOutput(kLoggingPrefix + "TargetHeading", targetHeading);
Logger.recordOutput(kLoggingPrefix + "TranslationalVelocityAngle", fieldRelativeVelocityHeading);

if (detectedNoteHeading.isEmpty()
|| mRobotState.hasNote()
|| Math.abs(mRotationSupplier.getAsDouble()) > 0.5
|| !GeometryUtil.isNear(
fieldRelativeVelocityHeading,
detectedNoteHeading.get(),
Rotation2d.fromDegrees(toleranceDegrees))) {
mDrive.setVelocity(new ChassisSpeeds(
translationVelocities.getX(), translationVelocities.getY(), rotationRadiansPerSecond));
return;
}

Rotation2d setpoint;
double rotationalVelocity;
if (GeometryUtil.isNear(GeometryUtil.kRotationIdentity, headingError, headingTolerance)
&& Util.epsilonEquals(mThrottleSupplier.getAsDouble(), 0)
&& Util.epsilonEquals(mStrafeSupplier.getAsDouble(), 0)) {
rotationalVelocity = 0;
mRotationState = kZeroState;
setpoint = targetHeading;
} else {
var rotationPidOutput = mRotationController.calculate(headingError.getRadians(), mRotationState.position);
mRotationState = mRotationProfile.calculate(Constants.kLoopPeriodSeconds, mRotationState, kZeroState);
rotationalVelocity = mRotationState.velocity + rotationPidOutput;
setpoint = Rotation2d.fromRadians(targetHeading.getRadians() + mRotationState.position);
}

mDrive.setVelocity(new ChassisSpeeds(
translationVelocities.getX(),
translationVelocities.getY(),
-rotationalVelocity + (rotationRadiansPerSecond * 0.5)));
Logger.recordOutput(kLoggingPrefix + "Setpoint", new Pose2d(endTranslation, setpoint));
}

@Override
public void end(boolean interrupted) {
mDrive.stop();
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/team1701/robot/controls/StreamDeck.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static enum StreamDeckButton {
kStopShootButton(1, 3, "Controls/StopShootButton", "StopShooterIcon", "Stop"),
kSpeakerModeButton(0, 4, "Controls/SpeakerModeButton", "SpeakerModeIcon", "Speaker"),
kAmpModeButton(1, 4, "Controls/AmpModeButton", "AmpModeIcon", "Amp"),
kClimbModeButton(2, 4, "Controls/ClimbModeButton", "ClimbModeIcon", "Climb"),
kDriveAssistButton(2, 4, "Controls/DriveAssistButton", "Circle", "Assist"),
kExtendWinchButton(0, 2, "Controls/ExtendWinchButton", "ExtendWinchIcon", "Extend"),
kRetractWinchButton(2, 2, "Controls/RetractWinchButton", "RetractWinchIcon", "Retract");

Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/team1701/robot/states/RobotState.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.function.Supplier;

import com.team1701.lib.drivers.cameras.neural.DetectorCamera.DetectedObjectState;
Expand Down Expand Up @@ -320,6 +321,27 @@ public Optional<DetectedObjectState> getDetectedNoteForPickup() {
return mDetectedNoteForPickup;
}

public Optional<Rotation2d> getHeadingToDetectedNoteForPickup() {
return getDetectedNoteForPickup().map(detectedNote -> detectedNote
.pose()
.toPose2d()
.getTranslation()
.minus(getPose2d().getTranslation())
.getAngle());
}

public OptionalDouble getDistanceToDetectedNoteForPickup() {
if (getDetectedNoteForPickup().isPresent()) {
return OptionalDouble.of(getDetectedNoteForPickup()
.get()
.pose()
.toPose2d()
.getTranslation()
.getDistance(getPose2d().getTranslation()));
}
return OptionalDouble.empty();
}

public void addDetectedNotes(List<DetectedObjectState> notes) {
var robotTranslation = getPose2d().getTranslation();
notes = notes.stream()
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/team1701/robot/subsystems/drive/Drive.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public class Drive extends SubsystemBase {
private TimeLockedBoolean mWasMovingRecently = new TimeLockedBoolean(1.0, 0.0, false, false);
private DriveControlState mDriveControlState = DriveControlState.VELOCITY_CONTROL;

private boolean mUseDriveAssist;

@AutoLogOutput(key = "Drive/MeasuredStates")
private SwerveModuleState[] mMeasuredModuleStates;

Expand Down Expand Up @@ -108,6 +110,8 @@ public Drive(GyroIO gyroIO, SwerveModuleIO[] moduleIOs, RobotState robotState) {
.onTrue(Commands.runOnce(() -> setDriveBrakeMode(false))
.ignoringDisable(true)
.withName("DriveEnabledStart"));

mUseDriveAssist = false;
}

@Override
Expand Down Expand Up @@ -349,6 +353,19 @@ public KinematicLimits getKinematicLimits() {
return mKinematicLimits;
}

public boolean useDriveAssist() {
return mUseDriveAssist;
}

public void setUseDriveAssist(boolean enable) {
mUseDriveAssist = enable;
}

public boolean toggleDriveAssist() {
setUseDriveAssist(!mUseDriveAssist);
return mUseDriveAssist;
}

public enum DriveControlState {
VELOCITY_CONTROL,
ORIENT_MODULES,
Expand Down
Loading

0 comments on commit 67111cf

Please sign in to comment.