Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shuffleboard abstraction #31

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9d0ba93
`GRTShuffleboardLayout`, `.list()`, positions in code
ky28059 Mar 29, 2022
fa5b47e
Position and size methods for shuffleboard layout
ky28059 Mar 29, 2022
4bc05fd
Internals debugging and networktables
ky28059 Mar 30, 2022
ff0ca1a
Move `.addEntry()` to list-like `.at()` position syntax
ky28059 Mar 30, 2022
e329d83
Auton chooser, split up localize coordinate method
ky28059 Mar 30, 2022
8794024
2 ball auto + more debug networktables
ky28059 Mar 30, 2022
d9d2fba
Run intake in `DeployIntakeCommand`, `PlebAutonSequence` restructuring
ky28059 Mar 30, 2022
5a01184
Put hood and flywheel refs on shuffleboard, reset offsets on vision data
ky28059 Mar 30, 2022
e9aef3a
internals and turret tweaks
e3l Mar 30, 2022
6108af2
Separate driver and auto intake override, partially revert PlebAutonS…
ky28059 Mar 31, 2022
46639fc
Merge branch 'shuffleboard-abstraction' of https://github.com/grt192/…
ky28059 Mar 31, 2022
0a7c144
Jetson data pairing
ky28059 Mar 31, 2022
1c7d9a7
Shoot 2 balls at once, rtheta feedforward, turntable tolerance fix
ky28059 Apr 1, 2022
4f383e3
tweaked and tested shooter interpolation table
e3l Apr 1, 2022
0bba935
Two ball fixes
e3l Apr 1, 2022
58db64d
Only shoot two balls without delay when they are the same color
ky28059 Apr 1, 2022
d94c188
`.widget()`, better internals shuffleboard updating
ky28059 Apr 1, 2022
e3023e4
Intake shuffleboard organization
ky28059 Apr 4, 2022
207fa74
Climb shuffleboard organization
ky28059 Apr 4, 2022
827e399
Intake top limit switch + reset abstraction
e3l Apr 4, 2022
2c64a8c
Preliminary intake deploy tuning
ky28059 Apr 4, 2022
e53ea54
Intake tuning, shuffleboard manual zero
ky28059 Apr 6, 2022
76f28f3
Turret `setValue()` organization
ky28059 Apr 6, 2022
39fa9b6
Don't force if the turret is retracted
ky28059 Apr 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static final class JetsonConstants {
public static final int turretCameraPort = 1181;
public static final int intakeCameraPort = 1182;
public static final int jetsonPort = 5800;
public static final String jetsonIP = "10.1.92.94";
public static final String jetsonIP = "10.1.92.12";
}

public static final class ShuffleboardConstants {
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 @@ -126,7 +126,7 @@ public void testInit() {
// Sweep intake from -1 to 1 power
intakeSubsystem.setDriverOverride(true);
for (double pow = -1; pow <= 1; pow += 0.1) {
intakeSubsystem.setIntakePower(pow);
intakeSubsystem.setDriverPower(pow);
Timer.delay(0.1);
}
intakeSubsystem.setDriverOverride(false);
Expand Down
69 changes: 24 additions & 45 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@

package frc.robot;

import java.util.List;

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.util.Units;
import edu.wpi.first.networktables.EntryListenerFlags;
import edu.wpi.first.networktables.EntryNotification;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.XboxController;
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.InstantCommand;
import edu.wpi.first.wpilibj2.command.RunCommand;
Expand All @@ -32,9 +27,9 @@
import frc.robot.commands.tank.AutonRedBottomSequence;
import frc.robot.commands.tank.AutonRedMiddleSequence;
import frc.robot.commands.tank.AutonRedTopSequence;
import frc.robot.commands.tank.FollowPathCommand;
import frc.robot.commands.tank.PlebAutonSequence;
import frc.robot.jetson.JetsonConnection;
import frc.robot.shuffleboard.GRTShuffleboardTab;
import frc.robot.subsystems.ClimbSubsystem;
import frc.robot.subsystems.IntakeSubsystem;
import frc.robot.subsystems.TurretSubsystem;
Expand Down Expand Up @@ -77,11 +72,11 @@ public class RobotContainer {
mechRBumper = new JoystickButton(mechController, XboxController.Button.kRightBumper.value);

// Commands
private Command autonCommand;
private final SendableChooser<Command> autonChooser;

// Debug flags
// Whether to run an auton path or skip auton and set starting position manually.
private static final boolean SKIP_AUTON = false;
// Whether to set starting position manually. This position will still be overriden if an auton sequence is run.
private static final boolean MANUAL_START_POS = true;

/**
* The container for the robot. Contains subsystems, OI devices, and commands.
Expand Down Expand Up @@ -111,25 +106,26 @@ public RobotContainer() {
// Configure the button bindings
configureButtonBindings();

// Instantiate auton command.
// If skipping autonomous, run an empty command in auton and set initial position
// from a manual hub distance. This assumes we are facing directly away from the hub
// at 0 degrees with a distance of `hubDist` between the robot and the hub.
if (SKIP_AUTON) {
// Add auton sequences to the chooser and add the chooser to shuffleboard
autonChooser = new SendableChooser<>();
autonChooser.addOption("Red top", new AutonRedTopSequence(this));
autonChooser.addOption("Red middle", new AutonRedMiddleSequence(this));
autonChooser.addOption("Red bottom", new AutonRedBottomSequence(this));
autonChooser.addOption("Blue top", new AutonBlueTopSequence(this));
autonChooser.addOption("Blue middle", new AutonBlueMiddleSequence(this));
autonChooser.addOption("Blue bottom", new AutonBlueBottomSequence(this));
autonChooser.setDefaultOption("Pleb auton", PlebAutonSequence.from(this));
autonChooser.addOption("Skip auton", new InstantCommand());

new GRTShuffleboardTab("Drivetrain").addWidget("Auton sequence", autonChooser);

// If setting initial position manually, start it at a position assuming we are facing the hub
// at a distance `hubDist` inches and 0 on the y axis.
// TODO: is this worth having be a flag at all?
if (MANUAL_START_POS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel like we need a starting position anyways, we might as well make it something like 70, 0 instead of 0, 0 and keep this flag on. Cuz auto will overwrite it anyways

double hubDist = 70;
Pose2d initialPose = new Pose2d(Units.inchesToMeters(hubDist), 0, new Rotation2d());
setInitialPosition(initialPose);

autonCommand = new InstantCommand();
} else {
// Set the auton command from the shuffleboard int.
// 1, 2, 3 -> red top, middle, bottom
// 4, 5, 6 -> blue top, middle, bottom
// 7 -> pleb auton sequence
// 8 -> InstantCommand (skip auton)
int autonSequence = 7;
Shuffleboard.getTab("Drivetrain").add("Auton sequence", autonSequence).getEntry()
.addListener(this::setAutonCommand, EntryListenerFlags.kImmediate | EntryListenerFlags.kUpdate | EntryListenerFlags.kNew);
}
}

Expand All @@ -150,7 +146,7 @@ public RobotContainer() {
* X button -> start climb sequence (climb)
*/
private void configureButtonBindings() {
// driveAButton.whenPressed(new RequestShotCommand(internalSubsystem));
driveAButton.whenPressed(new RequestShotCommand(internalSubsystem));
// driveBButton.whenPressed(new DeployIntakeCommand(intakeSubsystem));
// driveYButton.whenPressed(new RaiseIntakeCommand(intakeSubsystem));
driveXButton.whenPressed(new InstantCommand(turretSubsystem::toggleClimb));
Expand Down Expand Up @@ -212,29 +208,12 @@ private void configureButtonBindings() {
}, climbSubsystem));
}

/**
* Sets the selected auton command from the shuffleboard integer value.
* @param change The EntryNotification representing a shuffleboard value change.
*/
private void setAutonCommand(EntryNotification change) {
switch ((int) change.value.getDouble()) {
case 1: autonCommand = new AutonRedTopSequence(this); break;
case 2: autonCommand = new AutonRedMiddleSequence(this); break;
case 3: autonCommand = new AutonRedBottomSequence(this); break;
case 4: autonCommand = new AutonBlueTopSequence(this); break;
case 5: autonCommand = new AutonBlueMiddleSequence(this); break;
case 6: autonCommand = new AutonBlueBottomSequence(this); break;
case 7: autonCommand = new PlebAutonSequence(this); break;
case 8: autonCommand = new InstantCommand(); break;
}
}

/**
* Use this to pass the autonomous command to the main {@link Robot} class.
* @return the command to run in autonomous
*/
public Command getAutonomousCommand() {
return autonCommand;
return autonChooser.getSelected();
}

/**
Expand Down
21 changes: 16 additions & 5 deletions src/main/java/frc/robot/commands/intake/DeployIntakeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,27 @@
import frc.robot.subsystems.IntakeSubsystem;
import frc.robot.subsystems.IntakeSubsystem.IntakePosition;

/**
* Deploys and runs the intake at a supplied power (defaults to 1.0).
*/
public class DeployIntakeCommand extends InstantCommand {
private final IntakeSubsystem intake;
private final IntakeSubsystem intakeSubsystem;
private final double intakePow;

public DeployIntakeCommand(IntakeSubsystem intake) {
this.intake = intake;
addRequirements(intake);
public DeployIntakeCommand(IntakeSubsystem intakeSubsystem, double intakePow) {
this.intakeSubsystem = intakeSubsystem;
this.intakePow = intakePow;
addRequirements(intakeSubsystem);
}

public DeployIntakeCommand(IntakeSubsystem intakeSubsystem) {
this(intakeSubsystem, 1.0);
}

@Override
public void initialize() {
intake.setPosition(IntakePosition.DEPLOYED);
intakeSubsystem.setPosition(IntakePosition.DEPLOYED);
intakeSubsystem.setAutoOverride(true);
intakeSubsystem.setAutoPower(intakePow);
}
}
14 changes: 9 additions & 5 deletions src/main/java/frc/robot/commands/intake/RaiseIntakeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@
import frc.robot.subsystems.IntakeSubsystem;
import frc.robot.subsystems.IntakeSubsystem.IntakePosition;

/**
* Raises the intake and stops the intake rollers.
*/
public class RaiseIntakeCommand extends InstantCommand {
private final IntakeSubsystem intake;
private final IntakeSubsystem intakeSubsystem;

public RaiseIntakeCommand(IntakeSubsystem intake) {
this.intake = intake;
addRequirements(intake);
public RaiseIntakeCommand(IntakeSubsystem intakeSubsystem) {
this.intakeSubsystem = intakeSubsystem;
addRequirements(intakeSubsystem);
}

@Override
public void initialize() {
intake.setPosition(IntakePosition.RAISED);
intakeSubsystem.setPosition(IntakePosition.RAISED);
intakeSubsystem.setAutoOverride(false);
}
}
4 changes: 2 additions & 2 deletions src/main/java/frc/robot/commands/intake/RunIntakeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ public RunIntakeCommand(IntakeSubsystem intakeSubsystem, XboxController xboxCont
double leftTrigger = xboxController.getLeftTriggerAxis();
double rightTrigger = xboxController.getRightTriggerAxis();

intakeSubsystem.setIntakePower(rightTrigger - leftTrigger);
intakeSubsystem.setDriverPower(rightTrigger - leftTrigger);

// If the driver is supplying intake power with the triggers, override intake control
if (leftTrigger > 0 || rightTrigger > 0) {
intakeSubsystem.setDriverOverride(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class AutonBlueBottomSequence extends GRTAutonSequence {
Units.inchesToMeters(5.472),
Units.inchesToMeters(-60.540),
Rotation2d.fromDegrees(-66)); // TODO: are negative angles ok?
private static final Pose2d ballOnePose = localizeBallCoordinate(LEFT_BOTTOM_BLUE, 260.251594482);
private static final Pose2d ballOnePose = localizeToIntakeFront(LEFT_BOTTOM_BLUE, 260.251594482);

public AutonBlueBottomSequence(RobotContainer robotContainer) {
super(robotContainer, initialPose, ballOnePose);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public class AutonBlueMiddleSequence extends GRTAutonSequence {
Units.inchesToMeters(-44.575),
Units.inchesToMeters(-41.328),
Rotation2d.fromDegrees(204));
private static Pose2d ballOnePose = localizeBallCoordinate(LEFT_MID_BLUE, 215.248230);
private static Pose2d ballTwoPose = localizeBallCoordinate(TERMINAL_BLUE, 225);
private static Pose2d ballOnePose = localizeToRobotFront(LEFT_MID_BLUE, 215.248230);
private static Pose2d ballTwoPose = localizeToIntakeFront(TERMINAL_BLUE, 225);

public AutonBlueMiddleSequence(RobotContainer robotContainer) {
super(robotContainer, initialPose, ballOnePose, ballTwoPose);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class AutonBlueTopSequence extends GRTAutonSequence {
Units.inchesToMeters(-41.328),
Units.inchesToMeters(44.575),
Rotation2d.fromDegrees(114));
private static final Pose2d ballOnePose = localizeBallCoordinate(LEFT_TOP_BLUE, 147.74823);
private static final Pose2d ballOnePose = localizeToRobotFront(LEFT_TOP_BLUE, 147.74823);

public AutonBlueTopSequence(RobotContainer robotContainer) {
super(robotContainer, initialPose, ballOnePose);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class AutonRedBottomSequence extends GRTAutonSequence {
Units.inchesToMeters(41.328),
Units.inchesToMeters(-44.575),
Rotation2d.fromDegrees(-66)); // TODO: are negative angles ok?
private static final Pose2d ballOnePose = localizeBallCoordinate(RIGHT_BOTTOM_RED, -32.2517702051);
private static final Pose2d ballOnePose = localizeToRobotFront(RIGHT_BOTTOM_RED, -32.2517702051);

public AutonRedBottomSequence(RobotContainer robotContainer) {
super(robotContainer, initialPose, ballOnePose);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public class AutonRedMiddleSequence extends GRTAutonSequence {
Units.inchesToMeters(44.575),
Units.inchesToMeters(41.328),
Rotation2d.fromDegrees(24));
private static Pose2d ballOnePose = localizeBallCoordinate(RIGHT_MID_RED, 35.2482302738);
private static Pose2d ballTwoPose = localizeBallCoordinate(TERMINAL_RED, 45);
private static Pose2d ballOnePose = localizeToRobotFront(RIGHT_MID_RED, 35.2482302738);
private static Pose2d ballTwoPose = localizeToIntakeFront(TERMINAL_RED, 45);

public AutonRedMiddleSequence(RobotContainer robotContainer) {
super(robotContainer, initialPose, ballOnePose, ballTwoPose);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class AutonRedTopSequence extends GRTAutonSequence {
Units.inchesToMeters(-5.472),
Units.inchesToMeters(60.540),
Rotation2d.fromDegrees(114));
private static final Pose2d ballOnePose = localizeBallCoordinate(RIGHT_TOP_RED, 90);
private static final Pose2d ballOnePose = localizeToIntakeFront(RIGHT_TOP_RED, 90);

public AutonRedTopSequence(RobotContainer robotContainer) {
super(robotContainer, initialPose, ballOnePose);
Expand Down
59 changes: 47 additions & 12 deletions src/main/java/frc/robot/commands/tank/GRTAutonSequence.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@
* The superclass for all auton sequences, containing helper methods and shared constructor logic.
*/
public abstract class GRTAutonSequence extends SequentialCommandGroup {
private final RobotContainer robotContainer;
private final TankSubsystem tankSubsystem;
private final InternalSubsystem internalSubsystem;
private final IntakeSubsystem intakeSubsystem;

private final Pose2d initialPose;

/**
* Creates a GRTAutonSequence from an initial and ball one pose. This is used for shared initialization logic
* between all auton paths, as well as one-ball sequences like the top and bottom paths. Drives to the ball,
Expand All @@ -34,31 +37,39 @@ public abstract class GRTAutonSequence extends SequentialCommandGroup {
* @param ballOnePose The first ball pose of the sequence.
*/
public GRTAutonSequence(RobotContainer robotContainer, Pose2d initialPose, Pose2d ballOnePose) {
this.robotContainer = robotContainer;
this.initialPose = initialPose;

tankSubsystem = robotContainer.getTankSubsystem();
internalSubsystem = robotContainer.getInternalSubsystem();
intakeSubsystem = robotContainer.getIntakeSubsystem();

addRequirements(tankSubsystem, internalSubsystem, intakeSubsystem);
robotContainer.setInitialPosition(initialPose);

addCommands(
new DeployIntakeCommand(intakeSubsystem), // TODO: actually supply power to intake and rely on autodeploy
new DeployIntakeCommand(intakeSubsystem),
new FollowPathCommand(tankSubsystem, initialPose, List.of(), ballOnePose)
.withTimeout(5),
new ShootCommand(internalSubsystem),
new ShootCommand(internalSubsystem)
);
}

@Override
public void initialize() {
robotContainer.setInitialPosition(initialPose);
}

/**
* Creates a GRTAutonSequence from an initial, ball one, back, and final pose. This is used for the red top and
* blue bottom paths, where we may not taxi if we just drive to the ball; the wall is too close. Drives to
* the ball, shoots twice, then drives in reverse through the back waypoint to the final (taxi) pose.
* the ball, shoots twice, then drives to the final pose.
*
* @param robotContainer The RobotContainer instance, for calling `.setInitialPose()`.
* @param initialPose The initial pose of the sequence.
* @param ballOnePose The first ball pose of the sequence.
* @param finalPose The ending pose of the sequence.
* @param finalReversed Whether the command should drive to the final pose in reverse.
*/
public GRTAutonSequence(RobotContainer robotContainer, Pose2d initialPose, Pose2d ballOnePose, Pose2d finalPose, boolean finalReversed) {
this(robotContainer, initialPose, ballOnePose);
Expand Down Expand Up @@ -99,24 +110,48 @@ public GRTAutonSequence(RobotContainer robotContainer, Pose2d initialPose, Pose2
}

/**
* Localizes a ball coordinate to a robot pose used in path following. The robot cannot path follow
* directly to the ball coordinate, as the robot's position is based on the center of the chassis;
* instead, the robot should path follow to the Pose2d localized from the intake and chassis width.
* Localizes a ball coordinate to a robot pose used in path following by using the coordinate of the ball
* touching the front of the robot at an approach of `angleOfApproach` degrees.
*
* @param ball The ball coordinate, represented as a Translation2d.
* @param angleOfApproach The angle the robot should approach the ball, in degrees.
* @return The Pose2d to path follow to.
*/
protected static Pose2d localizeBallCoordinate(Translation2d ball, double angleOfApproach) {
// Robot length / 2
double h = 34 / 2;
protected static Pose2d localizeToRobotFront(Translation2d ball, double angleOfApproach) {
return localize(ball, angleOfApproach, 34 / 2); // Robot width / 2
}

/**
* Localizes a ball coordinate to a robot pose used in path following by using the coordinate of the ball
* touching the front of the intake at an approach of `angleOfApproach` degrees.
*
* @param ball The ball coordinate, represented as a Translation2d.
* @param angleOfApproach The angle the robot should approach the ball, in degrees.
* @return The Pose2d to path follow to.
*/
protected static Pose2d localizeToIntakeFront(Translation2d ball, double angleOfApproach) {
return localize(ball, angleOfApproach, 34 / 2 + 11.743); // Robot width / 2 + intake width
}

/**
* Localizes a ball coordinate to a robot pose used in path following by using the coordinate of the ball
* touching the center of the robot at an approach of `angleOfApproach` degrees.
*
* @param ball The ball coordinate, represented as a Translation2d.
* @param angleOfApproach The angle the robot should approach the ball, in degrees.
* @return The Pose2d to path follow to.
*/
protected static Pose2d localizeToRobotCenter(Translation2d ball, double angleOfApproach) {
return localize(ball, angleOfApproach, 0);
}

double rads = Math.toRadians(angleOfApproach);
private static Pose2d localize(Translation2d trans, double angle, double h) {
double rads = Math.toRadians(angle);
double dx = Units.inchesToMeters(h * Math.cos(rads));
double dy = Units.inchesToMeters(h * Math.sin(rads));

double x = ball.getX() - dx;
double y = ball.getY() - dy;
double x = trans.getX() - dx;
double y = trans.getY() - dy;
return new Pose2d(x, y, new Rotation2d(rads));
}
}
Loading