Skip to content

Commit

Permalink
Drive with joysticks fix (#36)
Browse files Browse the repository at this point in the history
* Transfers Joystick logic to seperate command

* Updates DriveWithJoysticks to have BooleanSupplier

* Update telemetry variable name
  • Loading branch information
honzikschenk authored Dec 14, 2023
1 parent 77d4cda commit 482a0bc
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 71 deletions.
4 changes: 4 additions & 0 deletions src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ public static final class DIOPorts {

public static final class DriveConstants {

public static final double MaxSpeedMetPerSec = 6;
public static final double MaxAngularRateRadiansPerSec = Math.PI * 2; // 2 PI is one full rotation per second
public static final double deadbandPercent = 0.16;

public static final double trackWidth = Units.inchesToMeters(17.75); // distance between the left and right wheels
public static final double wheelBase = Units.inchesToMeters(23.75); // distance between the front and rear wheels
public static final double wheelRadiusM = Units.inchesToMeters(2.02);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void robotInit() {
switch (Constants.currentMode) {
case REAL:
// Running on a real robot, log to a USB stick
Logger.addDataReceiver(new WPILOGWriter("/U"));
// Logger.addDataReceiver(new WPILOGWriter("/U")); TODO: Add this later
Logger.addDataReceiver(new NT4Publisher());
pdh = new PowerDistribution(1, ModuleType.kRev); // Enables power distribution logging
pdh.setSwitchableChannel(false);
Expand Down
82 changes: 13 additions & 69 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,96 +5,40 @@
package frc.robot;

import com.ctre.phoenix6.Utils;
import com.ctre.phoenix6.mechanisms.swerve.SwerveRequest;

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.wpilibj2.command.InstantCommand;
import edu.wpi.first.wpilibj2.command.button.CommandJoystick;
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import frc.robot.Constants.DriveConstants;
import frc.robot.commands.DriveWithJoysticks;
import frc.robot.generated.TunerConstants;

public class RobotContainer {
final double MaxSpeedMetPerSec = 6;
final double MaxAngularRateRadiansPerSec = Math.PI * 2; // 2 PI is one full rotation per second
final double deadbandPercent = 0.16;

/* Setting up bindings for necessary control of the swerve drive platform */
// Add a keyboard joystick for testing
CommandJoystick keyboardJoystick = new CommandJoystick(2); // Keyboard joystick for sim/debugging
CommandJoystick leftJoystick = new CommandJoystick(0); // Left joystick
CommandJoystick rightJoystick = new CommandJoystick(1); // Right joystick
CommandXboxController controller = new CommandXboxController(2); // Button Masher
CommandJoystick leftJoystick = new CommandJoystick(0);
CommandJoystick rightJoystick = new CommandJoystick(1);
CommandXboxController controller = new CommandXboxController(2);
CommandSwerveDrivetrain drivetrain = TunerConstants.DriveTrain;
SwerveRequest.FieldCentric drive = new SwerveRequest.FieldCentric().withIsOpenLoop(true);
SwerveRequest.RobotCentric driveRobot = new SwerveRequest.RobotCentric().withIsOpenLoop(true);
SwerveRequest.SwerveDriveBrake brake = new SwerveRequest.SwerveDriveBrake();
SwerveRequest.PointWheelsAt point = new SwerveRequest.PointWheelsAt();

Telemetry logger = new Telemetry(MaxSpeedMetPerSec);

// Grabs the left joystick x-axis with deadband applied
@SuppressWarnings("unused")
private double leftStickGetX() {
double rawInput = leftJoystick.getX();
return Math.abs(rawInput) > deadbandPercent ? rawInput : 0;
}

// Grabs the left joystick y-axis with deadband applied
@SuppressWarnings("unused")
private double leftStickGetY() {
double rawInput = leftJoystick.getY();
return Math.abs(rawInput) > deadbandPercent ? rawInput : 0;
}

// Grabs the right joystick x-axis with deadband applied
@SuppressWarnings("unused")
private double rightStickGetX() {
double rawInput = rightJoystick.getX();
return Math.abs(rawInput) > deadbandPercent ? rawInput : 0;
}

// Grabs the right joystick y-axis with deadband applied
@SuppressWarnings("unused")
private double rightStickGetY() {
double rawInput = rightJoystick.getY();
return Math.abs(rawInput) > deadbandPercent ? rawInput : 0;
}
Telemetry driveTelemetry = new Telemetry(DriveConstants.MaxSpeedMetPerSec);

private void configureBindings() {
drivetrain.setDefaultCommand(
drivetrain.applyRequest(() -> drive.withVelocityX(-leftStickGetY() * MaxSpeedMetPerSec)
.withVelocityY(-leftStickGetX() * MaxSpeedMetPerSec)
.withRotationalRate(-rightStickGetX() * MaxAngularRateRadiansPerSec)));

rightJoystick.trigger()
.whileTrue(
drivetrain.applyRequest(() -> driveRobot.withVelocityX(-leftStickGetY() * MaxSpeedMetPerSec)
.withVelocityY(-leftStickGetX() * MaxSpeedMetPerSec)
.withRotationalRate(-rightStickGetX() * MaxAngularRateRadiansPerSec)));

leftJoystick.trigger()
.whileTrue(drivetrain
.applyRequest(() -> drive.withVelocityX(-leftStickGetY() * MaxSpeedMetPerSec * 0.5)
.withVelocityY(-leftStickGetX() * MaxSpeedMetPerSec * 0.5)
.withRotationalRate(-rightStickGetX() * MaxAngularRateRadiansPerSec * 0.5)));
drivetrain.setDefaultCommand(new DriveWithJoysticks(drivetrain,
() -> leftJoystick.getY(),
() -> leftJoystick.getX(),
() -> rightJoystick.getX(),
() -> rightJoystick.trigger().getAsBoolean(),
() -> leftJoystick.trigger().getAsBoolean()));

rightJoystick.button(2)
.whileTrue(new InstantCommand(() -> drivetrain.seedFieldRelative()));

controller.a().whileTrue(drivetrain.applyRequest(() -> brake));
controller.b().whileTrue(drivetrain
.applyRequest(
() -> point
.withModuleDirection(new Rotation2d(-controller.getLeftY(), -controller.getLeftX()))));

controller.x().whileTrue(drivetrain.applyRequest(() -> drive.withIsOpenLoop(false)));

if (Utils.isSimulation()) {
drivetrain.seedFieldRelative(new Pose2d(new Translation2d(), Rotation2d.fromDegrees(90)));
}
drivetrain.registerTelemetry(logger::telemeterize);
drivetrain.registerTelemetry(driveTelemetry::telemeterize);
}

public void configureSubsystems() {
Expand Down
1 change: 0 additions & 1 deletion src/main/java/frc/robot/Telemetry.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.networktables.StringPublisher;
import edu.wpi.first.wpilibj.smartdashboard.Field2d;
import edu.wpi.first.wpilibj.smartdashboard.Mechanism2d;
import edu.wpi.first.wpilibj.smartdashboard.MechanismLigament2d;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
Expand Down
84 changes: 84 additions & 0 deletions src/main/java/frc/robot/commands/DriveWithJoysticks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package frc.robot.commands;

import java.util.function.BooleanSupplier;
import java.util.function.DoubleSupplier;

import com.ctre.phoenix6.mechanisms.swerve.SwerveRequest;

import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.CommandSwerveDrivetrain;
import frc.robot.Constants.DriveConstants;
import frc.robot.utils.Deadband;

public class DriveWithJoysticks extends Command {
CommandSwerveDrivetrain drivetrain;
DoubleSupplier x;
DoubleSupplier y;
DoubleSupplier rot;
BooleanSupplier fieldCentric;
BooleanSupplier babyMode;

double xMpS;
double yMpS;
double rotRadpS;

SwerveRequest.FieldCentric drive = new SwerveRequest.FieldCentric().withIsOpenLoop(true);
SwerveRequest.RobotCentric driveRobot = new SwerveRequest.RobotCentric().withIsOpenLoop(true);
SwerveRequest.SwerveDriveBrake brake = new SwerveRequest.SwerveDriveBrake();
SwerveRequest.PointWheelsAt point = new SwerveRequest.PointWheelsAt();

public DriveWithJoysticks(CommandSwerveDrivetrain drivetrain, DoubleSupplier x, DoubleSupplier y,
DoubleSupplier rot, BooleanSupplier fieldCentric, BooleanSupplier babyMode) {
this.drivetrain = drivetrain;
this.x = x;
this.y = y;
this.rot = rot;
this.fieldCentric = fieldCentric;
this.babyMode = babyMode;

addRequirements(drivetrain);
}

@Override
public void initialize() {
}

@Override
public void execute() {
double[] joystickInputsFiltered = Deadband.twoAxisDeadband(x.getAsDouble(), y.getAsDouble(),
DriveConstants.deadbandPercent);

xMpS = joystickInputsFiltered[0] * DriveConstants.MaxSpeedMetPerSec;
yMpS = joystickInputsFiltered[1] * DriveConstants.MaxSpeedMetPerSec;
rotRadpS = Deadband.oneAxisDeadband(rot.getAsDouble(), DriveConstants.deadbandPercent)
* DriveConstants.MaxAngularRateRadiansPerSec;

if (babyMode.getAsBoolean()) {
xMpS *= 0.5;
yMpS *= 0.5;
rotRadpS *= 0.5;
}

if (xMpS == 0 && yMpS == 0 && rotRadpS == 0) {
// If not moving, brake
drivetrain.applyRequest(() -> brake);
} else if (fieldCentric.getAsBoolean()) {
drivetrain.applyRequest(() -> drive.withVelocityX(-xMpS)
.withVelocityY(-yMpS)
.withRotationalRate(-rotRadpS));
} else {
drivetrain.applyRequest(() -> driveRobot.withVelocityX(-xMpS)
.withVelocityY(-yMpS)
.withRotationalRate(-rotRadpS));
}
}

@Override
public void end(boolean interrupted) {
}

@Override
public boolean isFinished() {
return false;
}
}
40 changes: 40 additions & 0 deletions src/main/java/frc/robot/utils/Deadband.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package frc.robot.utils;

public class Deadband {
// 1D Deadband in linear format
public static double oneAxisDeadband(double input, double deadband) {
if (Math.abs(input) < deadband) {
return 0;
} else {
return input;
}
}

// 2D Deadband in a circular format
public static double[] twoAxisDeadband(double inputX, double inputY, double deadband) {
double[] output = new double[2];
if (Math.sqrt(Math.pow(inputX, 2) + Math.pow(inputY, 2)) < deadband) {
output[0] = 0;
output[1] = 0;
} else {
output[0] = inputX;
output[1] = inputY;
}
return output;
}

// 3D Deadband in a spherical format
public static double[] threeAxisDeadband(double inputX, double inputY, double inputZ, double deadband) {
double[] output = new double[3];
if (Math.sqrt(Math.pow(inputX, 2) + Math.pow(inputY, 2) + Math.pow(inputZ, 2)) < deadband) {
output[0] = 0;
output[1] = 0;
output[2] = 0;
} else {
output[0] = inputX;
output[1] = inputY;
output[2] = inputZ;
}
return output;
}
}

0 comments on commit 482a0bc

Please sign in to comment.