Skip to content

Commit

Permalink
Demo mode (#197)
Browse files Browse the repository at this point in the history
* Add skeleton of AutomatedTeleop command

* Make AutomatedTeleop command drive automatically

* Update secretary and add diagram for AutomatedTeleop command

* add rotation override when align state is set to aligning

* forgot format

* remove align state manual in driveToPose / driveToPath

* format

* add demo mode to drivetrain

* remove automated teleop drive to path with demo

* add demo shooting

* adjust demo constants and logic for shooter ready

---------

Co-authored-by: aidnem <[email protected]>
Co-authored-by: minhnguyenbhs <[email protected]>
  • Loading branch information
3 people authored Nov 3, 2024
1 parent 857687c commit cc1b40b
Show file tree
Hide file tree
Showing 10 changed files with 392 additions and 53 deletions.
6 changes: 6 additions & 0 deletions doc/AutomatedTeleop.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
↓ Prev | Next → ,START,DRIVE_TO_SOURCE,ACQUIRE_NOTE,DRIVE_TO_SPEAKER,SHOOT_NOTE
START,default,!hasNote(),Not allowed,hasNote(),Not allowed
DRIVE_TO_SOURCE,Not allowed,default,Near Source? || Note Detected?,Not allowed,Not allowed
ACQUIRE_NOTE,Not allowed,Not allowed,default,hasNote(),Not allowed
DRIVE_TO_SPEAKER,Not allowed,!hasNote(),Not allowed,default,In range?
SHOOT_NOTE,Not allowed,!hasNote(),Not allowed,Not allowed,default
43 changes: 43 additions & 0 deletions doc/AutomatedTeleop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# AutomatedTeleop Subsystem
```mermaid
flowchart TD
classDef state font-size:40px,padding:10px
node0:::state
node0([<font size=11>START])
node1:::state
node1([<font size=11>DRIVE_TO_SOURCE])
node2:::state
node2([<font size=11>ACQUIRE_NOTE])
node3:::state
node3([<font size=11>DRIVE_TO_SPEAKER])
node4:::state
node4([<font size=11>SHOOT_NOTE])
node0 --> node5
node5 -.->|false| node1
node5{"hasNote()"}
node5 -.->|true| node3
node1 --> node6
node6{"Near Source?"}
node6 -.->|true| node2
node6 -.->|false| node7
node7{"Note Detected?"}
node7 -.->|true| node2
node7 -.->|false| node1
node2 --> node8
node8{"hasNote()"}
node8 -.->|true| node3
node8 -.->|false| node2
node3 --> node9
node9{"!hasNote()"}
node9 -.->|true| node1
node9 -.->|false| node10
node10{"In range?"}
node10 -.->|true| node4
node10 -.->|false| node3
node4 --> node11
node11{"!hasNote()"}
node11 -.->|true| node1
node11 -.->|false| node4
```
25 changes: 25 additions & 0 deletions src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public static final class FeatureFlags {
public static final boolean runScoring = true;
public static final boolean runEndgame = true;
public static final boolean runDrive = true;
public static final boolean demoMode = true;

public static final boolean enableLEDS = true;
}
Expand Down Expand Up @@ -114,6 +115,17 @@ public static final class DriveConstants {
public static final double vYkD = 0.0;
}

public static final class AutomatedTeleopConstants {
// TODO: Find constants for automated teleop command
public static final double intakeTimeoutSeconds = 0.5;
public static final double retryIntakeWaitSeconds = 0.5;

public static final double shootRangeMeters = 3.0;

// The distance from the source at which to stop driving the robot
public static final double sourceRangeMeters = 1.5;
}

public static final class FieldConstants {
public static final double lengthM = 16.451;
public static final double widthM = 8.211;
Expand Down Expand Up @@ -173,6 +185,16 @@ public static final class FieldConstants {

public static final Pose2d robotAgainstRedAmpZone =
new Pose2d(13.74, 7.68, Rotation2d.fromDegrees(-90));

public static final Pose2d robotAgainstBlueSource =
new Pose2d(14.82, 0.69, Rotation2d.fromDegrees(-60));

public static final Pose2d robotAgainstRedSource =
new Pose2d(1.63, 0.69, Rotation2d.fromDegrees(60));

// TODO: Find actual coordinates of shop source
public static final Pose2d robotAgainstShopSource =
new Pose2d(8.30, 6.80, Rotation2d.fromDegrees(60));
}

public static final class VisionConstants {
Expand Down Expand Up @@ -553,6 +575,9 @@ public static final class ScoringConstants {
public static final double hoodMaxVelocity = 0.5;
public static final double hoodMaxAcceleration = 0.5;

public static final double demoShooterRPM = 1000;
public static final double demoAimAngle = 0.4;

// NOTE - This should be monotonically increasing
// Key - Distance in meters
// Value - Aimer angle in radians
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ public void configureSubsystems() {
if (FeatureFlags.runDrive) {
driveTelemetry =
new Telemetry(DriveConstants.MaxSpeedMetPerSec, new TelemetryIOLive());
if (FeatureFlags.demoMode) {
drivetrain.setDemo(true);
}
}

if (FeatureFlags.runScoring) {
Expand All @@ -143,6 +146,9 @@ public void configureSubsystems() {
new ShooterIOTalon(),
new AimerIORoboRio(),
new HoodIOSparkFlex());
if (FeatureFlags.demoMode) {
scoringSubsystem.setDemo(true);
}
}

if (FeatureFlags.runEndgame) {
Expand Down Expand Up @@ -393,6 +399,7 @@ private void configureBindings() {
}

if (FeatureFlags.runScoring) {
if(!FeatureFlags.demoMode) {
scoringSubsystem.setDefaultCommand(new ShootWithGamepad(
() -> rightJoystick.getHID().getRawButton(4),
controller.getHID()::getRightBumper,
Expand All @@ -401,6 +408,9 @@ private void configureBindings() {
controller.getHID()::getAButton,
controller.getHID()::getBButton, scoringSubsystem,
FeatureFlags.runDrive ? drivetrain::getAlignTarget : () -> AlignTarget.NONE));
} else {
controller.y().onTrue(new InstantCommand(() -> scoringSubsystem.setAction(ScoringAction.SHOOT))).onFalse(new InstantCommand(() -> scoringSubsystem.setAction(ScoringAction.WAIT)));
}

rightJoystick.button(11).onTrue(new InstantCommand(() -> scoringSubsystem.setArmDisabled(true)));
rightJoystick.button(16).onTrue(new InstantCommand(() -> scoringSubsystem.setArmDisabled(false)));
Expand Down
133 changes: 133 additions & 0 deletions src/main/java/frc/robot/commands/AutomatedTeleop.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package frc.robot.commands;

import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.Constants.AutomatedTeleopConstants;
import frc.robot.Constants.FieldConstants;
import frc.robot.subsystems.drive.CommandSwerveDrivetrain;
import frc.robot.subsystems.intake.IntakeSubsystem;
import frc.robot.subsystems.intake.IntakeSubsystem.IntakeAction;
import frc.robot.subsystems.scoring.ScoringSubsystem;
import frc.robot.subsystems.scoring.ScoringSubsystem.ScoringAction;
import frc.robot.telemetry.Telemetry;
import java.util.function.Supplier;

public class AutomatedTeleop extends Command {
ScoringSubsystem scoringSubsystem;
IntakeSubsystem intakeSubsystem;
CommandSwerveDrivetrain drivetrain;

private Supplier<Pose2d> poseSupplier = () -> new Pose2d();

Telemetry telemetry;

private enum State {
START,
DRIVE_TO_SOURCE,
ACQUIRE_NOTE,
DRIVE_TO_SPEAKER,
SHOOT_NOTE,
}

private State state;

public AutomatedTeleop(
ScoringSubsystem scoringSubsystem,
IntakeSubsystem intakeSubsystem,
CommandSwerveDrivetrain drivetrain,
Telemetry telemetry,
Supplier<Pose2d> poseSupplier) {
this.scoringSubsystem = scoringSubsystem;
this.intakeSubsystem = intakeSubsystem;
this.drivetrain = drivetrain;
this.telemetry = telemetry;

this.poseSupplier = poseSupplier;

addRequirements(scoringSubsystem, intakeSubsystem, drivetrain);
}

@Override
public void initialize() {
this.state = State.START;

scoringSubsystem.setAction(ScoringAction.WAIT);
scoringSubsystem.forceHood(false);
}

private double findDistanceToSource() {
// NOTE: Leave one of the following lines commented out depending on the scenario:

// Uncomment this line for actual production code:
// Pose2d sourcePose = AllianceUtil.getPoseAgainstSource();

// Uncomment this line for testing with shop source
Pose2d sourcePose = FieldConstants.robotAgainstShopSource;

Pose2d robotPose = poseSupplier.get();
double distancetoGoal =
Math.sqrt(
Math.pow(Math.abs(robotPose.getX() - sourcePose.getX()), 2)
+ Math.pow(Math.abs(robotPose.getY() - sourcePose.getY()), 2));
return distancetoGoal;
}

@Override
public void execute() {
switch (state) {
case START:
if (intakeSubsystem.hasNote()) {
state = State.DRIVE_TO_SPEAKER;
} else {
state = State.DRIVE_TO_SOURCE;
}
break;
case DRIVE_TO_SOURCE:
drivetrain.driveToSource();

scoringSubsystem.setAction(ScoringAction.WAIT);
// Once robot reaches the source, stop driving and try to acquire a note
if (findDistanceToSource()
< AutomatedTeleopConstants.sourceRangeMeters /* || note detected */) {
state = State.ACQUIRE_NOTE;
}
break;
case ACQUIRE_NOTE:
// TODO: Fully implement automation of intake

drivetrain.stopDriveToPose();
intakeSubsystem.run(IntakeAction.INTAKE);

if (intakeSubsystem.hasNote()) {
state = State.DRIVE_TO_SPEAKER;
}
break;
case DRIVE_TO_SPEAKER:
// If we don't have a note, go get one
// This will work for if we drop our note or for after we've shot
if (!intakeSubsystem.hasNote()) {
// TODO: Use note vision to pick up a nearby note rather than going to source?
state = State.DRIVE_TO_SOURCE;
}

drivetrain.driveToSpeaker();
scoringSubsystem.setAction(ScoringAction.AIM);

// Once we are in range, shoot
if (scoringSubsystem.findDistanceToGoal()
< AutomatedTeleopConstants.shootRangeMeters) {
state = State.SHOOT_NOTE;
}
break;
case SHOOT_NOTE:
if (!intakeSubsystem.hasNote()) {
state = State.DRIVE_TO_SOURCE;
}

drivetrain.driveToSpeaker();
scoringSubsystem.setAction(ScoringAction.SHOOT);

break;
}
}
}
Loading

0 comments on commit cc1b40b

Please sign in to comment.