Skip to content

Commit

Permalink
Add part of YAGSL-Example
Browse files Browse the repository at this point in the history
Added part of our fork of YAGSL Example, which is not updated to 2024. This will fail builds and deploy.
  • Loading branch information
garrettsummerfi3ld committed Jan 20, 2024
1 parent c5333b6 commit 9733d40
Show file tree
Hide file tree
Showing 8 changed files with 818 additions and 32 deletions.
34 changes: 33 additions & 1 deletion src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

package frc.robot;

import edu.wpi.first.math.geometry.Translation3d;
import edu.wpi.first.math.util.Units;
import swervelib.math.Matter;
import swervelib.parser.PIDFConfig;

/**
* The Constants class provides a convenient place for teams to hold robot-wide numerical or boolean
* constants. This class should not be used for any other purpose. All constants should be declared
Expand All @@ -13,7 +18,34 @@
* constants are needed, to reduce verbosity.
*/
public final class Constants {

public static final double ROBOT_MASS = (148 - 20.3) * 0.453592; // 32lbs * kg per pound
public static final Matter CHASSIS =
new Matter(new Translation3d(0, 0, Units.inchesToMeters(8)), ROBOT_MASS);
public static final double LOOP_TIME = 0.13; // s, 20ms + 110ms sprk max velocity lag

public static final class Auton {

public static final PIDFConfig xAutoPID = new PIDFConfig(0.7, 0, 0);
public static final PIDFConfig yAutoPID = new PIDFConfig(0.7, 0, 0);
public static final PIDFConfig angleAutoPID = new PIDFConfig(0.4, 0, 0.01);

public static final double MAX_SPEED = 4;
public static final double MAX_ACCELERATION = 2;
}

public static final class Drivebase {

// Hold time on motor brakes when disabled
public static final double WHEEL_LOCK_TIME = 10; // seconds
}

public static class OperatorConstants {
public static final int kDriverControllerPort = 0;

// Joystick Deadband
public static final double LEFT_X_DEADBAND = 0.01;
public static final double LEFT_Y_DEADBAND = 0.01;
public static final double RIGHT_X_DEADBAND = 0.01;
public static final double TURN_CONSTANT = 0.75;
}
}
1 change: 1 addition & 0 deletions src/main/java/frc/robot/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* call.
*/
public final class Main {

private Main() {}

/**
Expand Down
57 changes: 51 additions & 6 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@

package frc.robot;

import com.pathplanner.lib.server.PathPlannerServer;
import edu.wpi.first.wpilibj.Filesystem;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.CommandScheduler;
import java.io.File;
import java.io.IOException;
import swervelib.parser.SwerveParser;

/**
* The VM is configured to automatically run this class, and to call the functions corresponding to
Expand All @@ -15,19 +21,39 @@
* project.
*/
public class Robot extends TimedRobot {

private static Robot instance;
private Command m_autonomousCommand;

private RobotContainer m_robotContainer;

private Timer disabledTimer;

public Robot() {
instance = this;
}

public static Robot getInstance() {
return instance;
}

/**
* This function is run when the robot is first started up and should be used for any
* initialization code.
*/
@Override
public void robotInit() {
// Instantiate our RobotContainer. This will perform all our button bindings, and put our
PathPlannerServer.startServer(5811);
// Instantiate our RobotContainer. This will perform all our button bindings,
// and put our
// autonomous chooser on the dashboard.
m_robotContainer = new RobotContainer();

// Create a timer to disable motor brake a few seconds after disable. This will
// let the robot
// stop
// immediately when disabled, but then also let it be pushed more
disabledTimer = new Timer();
}

/**
Expand All @@ -39,23 +65,36 @@ public void robotInit() {
*/
@Override
public void robotPeriodic() {
// Runs the Scheduler. This is responsible for polling buttons, adding newly-scheduled
// commands, running already-scheduled commands, removing finished or interrupted commands,
// and running subsystem periodic() methods. This must be called from the robot's periodic
// Runs the Scheduler. This is responsible for polling buttons, adding
// newly-scheduled
// commands, running already-scheduled commands, removing finished or
// interrupted commands,
// and running subsystem periodic() methods. This must be called from the
// robot's periodic
// block in order for anything in the Command-based framework to work.
CommandScheduler.getInstance().run();
}

/** This function is called once each time the robot enters Disabled mode. */
@Override
public void disabledInit() {}
public void disabledInit() {
m_robotContainer.setMotorBrake(true);
disabledTimer.reset();
disabledTimer.start();
}

@Override
public void disabledPeriodic() {}
public void disabledPeriodic() {
if (disabledTimer.hasElapsed(Constants.Drivebase.WHEEL_LOCK_TIME)) {
m_robotContainer.setMotorBrake(false);
disabledTimer.stop();
}
}

/** This autonomous runs the autonomous command selected by your {@link RobotContainer} class. */
@Override
public void autonomousInit() {
m_robotContainer.setMotorBrake(true);
m_autonomousCommand = m_robotContainer.getAutonomousCommand();

// schedule the autonomous command (example)
Expand All @@ -77,6 +116,7 @@ public void teleopInit() {
if (m_autonomousCommand != null) {
m_autonomousCommand.cancel();
}
m_robotContainer.setMotorBrake(true);
}

/** This function is called periodically during operator control. */
Expand All @@ -87,6 +127,11 @@ public void teleopPeriodic() {}
public void testInit() {
// Cancels all running commands at the start of test mode.
CommandScheduler.getInstance().cancelAll();
try {
new SwerveParser(new File(Filesystem.getDeployDirectory(), "swerve"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

/** This function is called periodically during test mode. */
Expand Down
52 changes: 27 additions & 25 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

package frc.robot;

import edu.wpi.first.wpilibj.Filesystem;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.InstantCommand;
import edu.wpi.first.wpilibj2.command.button.CommandJoystick;
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import edu.wpi.first.wpilibj2.command.button.Trigger;
import frc.robot.Constants.OperatorConstants;
import frc.robot.commands.Autos;
import frc.robot.commands.ExampleCommand;
import frc.robot.subsystems.ExampleSubsystem;
import frc.robot.commands.swervedrive.drivebase.SwerveCommand;
import frc.robot.subsystems.swervedrive.SwerveSubsystem;
import java.io.File;

/**
* This class is where the bulk of the robot should be declared. Since Command-based is a
Expand All @@ -19,36 +20,33 @@
* subsystems, commands, and trigger mappings) should be declared here.
*/
public class RobotContainer {

// The robot's subsystems and commands are defined here...
private final ExampleSubsystem m_exampleSubsystem = new ExampleSubsystem();
private final SwerveSubsystem drivebase =
new SwerveSubsystem(new File(Filesystem.getDeployDirectory(), "swerve"));

CommandJoystick driverController = new CommandJoystick(1);

// Replace with CommandPS4Controller or CommandJoystick if needed
private final CommandXboxController m_driverController =
new CommandXboxController(OperatorConstants.kDriverControllerPort);
CommandXboxController driverXbox = new CommandXboxController(0);

/** The container for the robot. Contains subsystems, OI devices, and commands. */
public RobotContainer() {

// Configure Swerve (Command)
configureDrive();

// Configure the trigger bindings
configureBindings();
}

/**
* Use this method to define your trigger->command mappings. Triggers can be created via the
* {@link Trigger#Trigger(java.util.function.BooleanSupplier)} constructor with an arbitrary
* predicate, or via the named factories in {@link
* edu.wpi.first.wpilibj2.command.button.CommandGenericHID}'s subclasses for {@link
* CommandXboxController Xbox}/{@link edu.wpi.first.wpilibj2.command.button.CommandPS4Controller
* PS4} controllers or {@link edu.wpi.first.wpilibj2.command.button.CommandJoystick Flight
* joysticks}.
*/
private void configureDrive() {
SwerveCommand swerveCommand = new SwerveCommand(drivebase, driverXbox);
drivebase.setDefaultCommand(swerveCommand);
}

private void configureBindings() {
// Schedule `ExampleCommand` when `exampleCondition` changes to `true`
new Trigger(m_exampleSubsystem::exampleCondition)
.onTrue(new ExampleCommand(m_exampleSubsystem));

// Schedule `exampleMethodCommand` when the Xbox controller's B button is pressed,
// cancelling on release.
m_driverController.b().whileTrue(m_exampleSubsystem.exampleMethodCommand());
driverController.button(10).toggleOnTrue(new InstantCommand(() -> drivebase.zeroGyro()));
}

/**
Expand All @@ -58,6 +56,10 @@ private void configureBindings() {
*/
public Command getAutonomousCommand() {
// An example command will be run in autonomous
return Autos.exampleAuto(m_exampleSubsystem);
return null;
}

public void setMotorBrake(boolean shouldBrake) {
drivebase.setMotorBrake(shouldBrake);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package frc.robot.commands.swervedrive.drivebase;

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.util.sendable.SendableBuilder;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj2.command.CommandBase;
import frc.robot.Constants;
import frc.robot.subsystems.swervedrive.SwerveSubsystem;
import java.util.List;
import java.util.function.DoubleSupplier;
import swervelib.SwerveController;
import swervelib.math.SwerveMath;

/** An example command that uses an example subsystem. */
public class AbsoluteDrive extends CommandBase {

private final SwerveSubsystem swerve;
private final DoubleSupplier vX, vY;
private final DoubleSupplier headingHorizontal, headingVertical;
private boolean initRotation = false;

/**
* Used to drive a swerve robot in full field-centric mode. vX and vY supply translation inputs,
* where x is torwards/away from alliance wall and y is left/right. headingHorzontal and
* headingVertical are the Cartesian coordinates from which the robot's angle will be derived—
* they will be converted to a polar angle, which the robot will rotate to.
*
* @param swerve The swerve drivebase subsystem.
* @param vX DoubleSupplier that supplies the x-translation joystick input. Should be in the range
* -1 to 1 with deadband already accounted for. Positive X is away from the alliance wall.
* @param vY DoubleSupplier that supplies the y-translation joystick input. Should be in the range
* -1 to 1 with deadband already accounted for. Positive Y is towards the left wall when
* looking through the driver station glass.
* @param headingHorizontal DoubleSupplier that supplies the horizontal component of the robot's
* heading angle. In the robot coordinate system, this is along the same axis as vY. Should
* range from -1 to 1 with no deadband. Positive is towards the left wall when looking through
* the driver station glass.
* @param headingVertical DoubleSupplier that supplies the vertical component of the robot's
* heading angle. In the robot coordinate system, this is along the same axis as vX. Should
* range from -1 to 1 with no deadband. Positive is away from the alliance wall.
*/
public AbsoluteDrive(
SwerveSubsystem swerve,
DoubleSupplier vX,
DoubleSupplier vY,
DoubleSupplier headingHorizontal,
DoubleSupplier headingVertical) {
this.swerve = swerve;
this.vX = vX;
this.vY = vY;
this.headingHorizontal = headingHorizontal;
this.headingVertical = headingVertical;

addRequirements(swerve);
}

@Override
public void initialize() {
initRotation = true;
}

// Called every time the scheduler runs while the command is scheduled.
@Override
public void execute() {

// Get the desired chassis speeds based on a 2 joystick module.
ChassisSpeeds desiredSpeeds =
swerve.getTargetSpeeds(
vX.getAsDouble(),
vY.getAsDouble(),
headingHorizontal.getAsDouble(),
headingVertical.getAsDouble());

// Prevent Movement After Auto
if (initRotation) {
if (headingHorizontal.getAsDouble() == 0 && headingVertical.getAsDouble() == 0) {
// Get the curretHeading
Rotation2d firstLoopHeading = swerve.getHeading();

// Set the Current Heading to the desired Heading
desiredSpeeds =
swerve.getTargetSpeeds(0, 0, firstLoopHeading.getSin(), firstLoopHeading.getCos());
}
// Dont Init Rotation Again
initRotation = false;
}

// Limit velocity to prevent tippy
Translation2d translation = SwerveController.getTranslation2d(desiredSpeeds);
translation =
SwerveMath.limitVelocity(
translation,
swerve.getFieldVelocity(),
swerve.getPose(),
Constants.LOOP_TIME,
Constants.ROBOT_MASS,
List.of(Constants.CHASSIS),
swerve.getSwerveDriveConfiguration());
SmartDashboard.putNumber("LimitedTranslation", translation.getX());
SmartDashboard.putString("Translation", translation.toString());

// Make the robot move
swerve.drive(translation, desiredSpeeds.omegaRadiansPerSecond, true);
}

// Called once the command ends or is interrupted.
@Override
public void end(boolean interrupted) {}

// Returns true when the command should end.
@Override
public boolean isFinished() {
return false;
}

@Override
public void initSendable(SendableBuilder builder) {
builder.addDoubleProperty(
"Target Rotation Speed",
() ->
swerve.getTargetSpeeds(
vX.getAsDouble(),
vY.getAsDouble(),
headingHorizontal.getAsDouble(),
headingVertical.getAsDouble())
.omegaRadiansPerSecond,
null);
}
}
Loading

0 comments on commit 9733d40

Please sign in to comment.