Skip to content

Commit

Permalink
Integrate the VTS
Browse files Browse the repository at this point in the history
  • Loading branch information
manthan-acharya committed Feb 10, 2024
1 parent ecf86d0 commit 70d5d71
Show file tree
Hide file tree
Showing 13 changed files with 353 additions and 427 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ task(generateDriveTrajectories, dependsOn: "classes", type: JavaExec) {
mainClass = "org.littletonrobotics.frc2024.subsystems.drive.trajectory.GenerateTrajectories"
classpath = sourceSets.main.runtimeClasspath
}
//compileJava.finalizedBy generateDriveTrajectories
compileJava.finalizedBy generateDriveTrajectories

// Check robot type when deploying
task(checkRobot, dependsOn: "classes", type: JavaExec) {
Expand Down Expand Up @@ -171,6 +171,7 @@ dependencies {
implementation "io.grpc:grpc-stub:${grpcVersion}"
implementation "javax.annotation:javax.annotation-api:1.3.2"
runtimeOnly "io.grpc:grpc-netty-shaded:${grpcVersion}"
implementation "com.google.guava:guava:31.1-jre"

def akitJson = new groovy.json.JsonSlurper().parseText(new File(projectDir.getAbsolutePath() + "/vendordeps/AdvantageKit.json").text)
annotationProcessor "org.littletonrobotics.akit.junction:junction-autolog:$akitJson.version"
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/littletonrobotics/frc2024/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*/
public final class Constants {
public static final int loopPeriodMs = 20;
private static RobotType robotType = RobotType.DEVBOT;
private static RobotType robotType = RobotType.SIMBOT;
public static final boolean tuningMode = true;

private static boolean invalidRobotAlertSent = false;
Expand Down
49 changes: 25 additions & 24 deletions src/main/java/org/littletonrobotics/frc2024/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,14 @@
import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.util.Units;
import edu.wpi.first.wpilibj.Filesystem;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.XboxController;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.Commands;
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import edu.wpi.first.wpilibj2.command.button.Trigger;
import java.io.File;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import org.littletonrobotics.frc2024.commands.FeedForwardCharacterization;
import org.littletonrobotics.frc2024.commands.auto.AutoCommands;
import org.littletonrobotics.frc2024.subsystems.apriltagvision.AprilTagVision;
import org.littletonrobotics.frc2024.subsystems.apriltagvision.AprilTagVisionConstants;
import org.littletonrobotics.frc2024.subsystems.apriltagvision.AprilTagVisionIO;
Expand All @@ -51,8 +47,6 @@
import org.littletonrobotics.frc2024.subsystems.superstructure.intake.IntakeIOKrakenFOC;
import org.littletonrobotics.frc2024.subsystems.superstructure.intake.IntakeIOSim;
import org.littletonrobotics.frc2024.util.AllianceFlipUtil;
import org.littletonrobotics.frc2024.util.trajectory.ChoreoTrajectoryDeserializer;
import org.littletonrobotics.frc2024.util.trajectory.HolonomicTrajectory;
import org.littletonrobotics.junction.networktables.LoggedDashboardChooser;

/**
Expand Down Expand Up @@ -168,6 +162,7 @@ public RobotContainer() {
}

autoChooser = new LoggedDashboardChooser<>("Auto Choices");
autoChooser.addDefaultOption("Do Nothing", Commands.none());
// Set up feedforward characterization
autoChooser.addOption(
"Drive FF Characterization",
Expand All @@ -188,24 +183,30 @@ public RobotContainer() {
flywheels::getRightCharacterizationVelocity));
autoChooser.addOption("Arm get static current", arm.getStaticCurrent());

AutoCommands autoCommands = new AutoCommands(drive, superstructure);

autoChooser.addOption("Drive Straight", autoCommands.driveStraight());

// Testing autos paths
Function<File, Optional<Command>> trajectoryCommandFactory =
trajectoryFile -> {
Optional<HolonomicTrajectory> trajectory =
ChoreoTrajectoryDeserializer.deserialize(trajectoryFile);
return trajectory.map(
traj ->
Commands.runOnce(
() -> robotState.resetPose(AllianceFlipUtil.apply(traj.getStartPose())))
.andThen(Commands.runOnce(() -> drive.setTrajectoryGoal(traj)))
.until(drive::isTrajectoryGoalCompleted));
};
final File rootTrajectoryDir = new File(Filesystem.getDeployDirectory(), "choreo");
for (File trajectoryFile : Objects.requireNonNull(rootTrajectoryDir.listFiles())) {
trajectoryCommandFactory
.apply(trajectoryFile)
.ifPresent(command -> autoChooser.addOption(trajectoryFile.getName(), command));
}
// Function<File, Optional<Command>> trajectoryCommandFactory =
// trajectoryFile -> {
// Optional<HolonomicTrajectory> trajectory =
// ChoreoTrajectoryDeserializer.deserialize(trajectoryFile);
// return trajectory.map(
// traj ->
// Commands.runOnce(
// () ->
// robotState.resetPose(AllianceFlipUtil.apply(traj.getStartPose())))
// .andThen(Commands.runOnce(() ->
// drive.setTrajectoryGoal(traj)))
// .until(drive::isTrajectoryGoalCompleted));
// };
// final File rootTrajectoryDir = new File(Filesystem.getDeployDirectory(), "choreo");
// for (File trajectoryFile : Objects.requireNonNull(rootTrajectoryDir.listFiles())) {
// trajectoryCommandFactory
// .apply(trajectoryFile)
// .ifPresent(command -> autoChooser.addOption(trajectoryFile.getName(), command));
// }

// Configure the button bindings
configureButtonBindings();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,44 @@
package org.littletonrobotics.frc2024.commands.auto;

import edu.wpi.first.math.geometry.Translation2d;
import static edu.wpi.first.wpilibj2.command.Commands.*;

import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.Commands;
import java.util.function.Supplier;
import org.littletonrobotics.frc2024.RobotState;
import org.littletonrobotics.frc2024.subsystems.drive.Drive;
import org.littletonrobotics.frc2024.subsystems.superstructure.Superstructure;
import org.littletonrobotics.frc2024.util.AllianceFlipUtil;
import org.littletonrobotics.frc2024.util.trajectory.HolonomicTrajectory;

public class AutoCommands {
private Drive drive;
private Superstructure superstructure;

public static boolean inRegion(Supplier<Region> region) {
return region.get().contains(RobotState.getInstance().getEstimatedPose().getTranslation());
}

public static Command waitForRegion(Supplier<Region> region) {
return Commands.waitUntil(() -> inRegion(region));
public AutoCommands(Drive drive, Superstructure superstructure) {
this.drive = drive;
this.superstructure = superstructure;
}

public interface Region {
boolean contains(Translation2d point);
private Command path(String pathName) {
HolonomicTrajectory trajectory = new HolonomicTrajectory(pathName);

return startEnd(
() -> {
drive.setTrajectoryGoal(trajectory);
},
() -> {
drive.clearTrajectoryGoal();
})
.until(() -> drive.isTrajectoryGoalCompleted());
}

public static class RectangularRegion implements Region {
public final Translation2d topLeft;
public final Translation2d bottomRight;

public RectangularRegion(Translation2d topLeft, Translation2d bottomRight) {
this.topLeft = topLeft;
this.bottomRight = bottomRight;
}

public RectangularRegion(Translation2d center, double width, double height) {
topLeft = new Translation2d(center.getX() - width / 2, center.getY() + height / 2);
bottomRight = new Translation2d(center.getX() + width / 2, center.getY() - height / 2);
}

public boolean contains(Translation2d point) {
return point.getX() >= topLeft.getX()
&& point.getX() <= bottomRight.getX()
&& point.getY() <= topLeft.getY()
&& point.getY() >= bottomRight.getY();
}
private Command reset(String path) {
HolonomicTrajectory trajectory = new HolonomicTrajectory(path);
return runOnce(
() ->
RobotState.getInstance().resetPose(AllianceFlipUtil.apply(trajectory.getStartPose())));
}

public record CircularRegion(Translation2d center, double radius) implements Region {
public boolean contains(Translation2d point) {
return center.getDistance(point) <= radius;
}
public Command driveStraight() {
return reset("driveStraight").andThen(path("driveStraight"));
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.littletonrobotics.frc2024.subsystems.drive.controllers;

import static org.littletonrobotics.frc2024.subsystems.drive.DriveConstants.trajectoryConstants;
import static org.littletonrobotics.vehicletrajectoryservice.VehicleTrajectoryServiceOuterClass.*;

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.geometry.Twist2d;
import edu.wpi.first.math.kinematics.ChassisSpeeds;
import edu.wpi.first.wpilibj.Timer;
Expand All @@ -26,25 +26,6 @@ public class TrajectoryController {
new LoggedTunableNumber("Trajectory/thetakP", trajectoryConstants.thetakP());
private static LoggedTunableNumber trajectoryThetakD =
new LoggedTunableNumber("Trajectory/thetakD", trajectoryConstants.thetakD());
private static LoggedTunableNumber trajectoryLinearTolerance =
new LoggedTunableNumber(
"Trajectory/controllerLinearTolerance", trajectoryConstants.linearTolerance());
private static LoggedTunableNumber trajectoryThetaTolerance =
new LoggedTunableNumber(
"Trajectory/controllerThetaTolerance", trajectoryConstants.thetaTolerance());
private static LoggedTunableNumber trajectoryGoalLinearTolerance =
new LoggedTunableNumber(
"Trajectory/goalLinearTolerance", trajectoryConstants.goalLinearTolerance());
private static LoggedTunableNumber trajectoryGoalThetaTolerance =
new LoggedTunableNumber(
"Trajectory/goalThetaTolerance", trajectoryConstants.goalThetaTolerance());
private static LoggedTunableNumber trajectoryLinearVelocityTolerance =
new LoggedTunableNumber(
"Trajectory/goalLinearVelocityTolerance", trajectoryConstants.linearVelocityTolerance());
private static LoggedTunableNumber trajectoryAngularVelocityTolerance =
new LoggedTunableNumber(
"Trajectory/goalAngularVelocityTolerance",
trajectoryConstants.angularVelocityTolerance());

private HolonomicDriveController controller;
private HolonomicTrajectory trajectory;
Expand All @@ -58,8 +39,7 @@ public TrajectoryController(HolonomicTrajectory trajectory) {
trajectoryLinearkD.get(),
trajectoryThetakP.get(),
trajectoryThetakD.get());
controller.setGoalState(AllianceFlipUtil.apply(trajectory.getEndState()));
configTrajectoryTolerances();

startTime = Timer.getFPGATimestamp();
// Log poses
Logger.recordOutput(
Expand All @@ -78,31 +58,34 @@ public ChassisSpeeds update() {
trajectoryLinearkD,
trajectoryThetakP,
trajectoryThetakP);
// Tolerances
LoggedTunableNumber.ifChanged(
hashCode(),
this::configTrajectoryTolerances,
trajectoryLinearTolerance,
trajectoryThetaTolerance,
trajectoryGoalLinearTolerance,
trajectoryGoalThetaTolerance,
trajectoryLinearVelocityTolerance,
trajectoryAngularVelocityTolerance);

// Run trajectory
Pose2d currentPose = RobotState.getInstance().getEstimatedPose();
Twist2d fieldVelocity = RobotState.getInstance().fieldVelocity();
double sampletime = Timer.getFPGATimestamp() - startTime;
HolonomicTrajectory.State currentState =
new HolonomicTrajectory.State(
sampletime, currentPose, fieldVelocity.dx, fieldVelocity.dy, fieldVelocity.dtheta);
VehicleState currentState =
VehicleState.newBuilder()
.setX(currentPose.getTranslation().getX())
.setY(currentPose.getTranslation().getY())
.setTheta(currentPose.getRotation().getRadians())
.setVx(fieldVelocity.dx)
.setVy(fieldVelocity.dy)
.setOmega(fieldVelocity.dtheta)
.build();
// Sample and flip state
HolonomicTrajectory.State setpointState = trajectory.sample(sampletime);
VehicleState setpointState = trajectory.sample(sampletime);
setpointState = AllianceFlipUtil.apply(setpointState);

// calculate trajectory speeds
ChassisSpeeds speeds = controller.calculate(currentState, setpointState);
// Log trajectory data
Logger.recordOutput("Trajectory/SetpointPose", setpointState.pose());
Logger.recordOutput(
"Trajectory/SetpointPose",
new Pose2d(
setpointState.getX(), setpointState.getY(), new Rotation2d(setpointState.getTheta())));
Logger.recordOutput("Trajectory/SetpointSpeeds/vx", setpointState.getVx());
Logger.recordOutput("Trajectory/SetpointSpeeds/vy", setpointState.getVy());
Logger.recordOutput("Trajectory/SetpointSpeeds/omega", setpointState.getOmega());
Logger.recordOutput("Trajectory/FieldRelativeSpeeds", speeds);
return speeds;
}
Expand All @@ -119,27 +102,6 @@ public Rotation2d getRotationError() {

@AutoLogOutput(key = "Trajectory/Finished")
public boolean isFinished() {
return Timer.getFPGATimestamp() - startTime > trajectory.getDuration()
&& controller.atGoal()
&& controller.atSetpoint();
}

private void configTrajectoryTolerances() {
controller.setControllerTolerance(
new Pose2d(
new Translation2d(
trajectoryLinearTolerance.get(), Rotation2d.fromRadians(Math.PI / 4.0)),
Rotation2d.fromRadians(trajectoryThetaTolerance.get())));
double velocityXTolerance = trajectoryLinearVelocityTolerance.get() / Math.sqrt(2.0);
controller.setGoalTolerance(
new HolonomicTrajectory.State(
0.0,
new Pose2d(
new Translation2d(
trajectoryGoalLinearTolerance.get(), Rotation2d.fromRadians(Math.PI / 4.0)),
Rotation2d.fromRadians(trajectoryGoalThetaTolerance.get())),
velocityXTolerance,
velocityXTolerance, // Same value
trajectoryAngularVelocityTolerance.get()));
return Timer.getFPGATimestamp() - startTime > trajectory.getDuration();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@

import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Rotation2d;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.experimental.ExtensionMethod;

@ExtensionMethod({TrajectoryGenerationHelpers.class})
public class DriveTrajectories {
public static final List<PathSegment> driveStraight =
List.of(
PathSegment.newBuilder()
.addPoseWaypoint(new Pose2d())
.addPoseWaypoint(new Pose2d(2.0, 0.0, new Rotation2d()), 100)
.build());
public static final Map<String, List<PathSegment>> paths = new HashMap<>();

static {
paths.put(
"driveStraight",
List.of(
PathSegment.newBuilder()
.addPoseWaypoint(new Pose2d())
.addPoseWaypoint(new Pose2d(2.0, 0.0, new Rotation2d()), 100)
.addPoseWaypoint(new Pose2d(4.0, 2.0, new Rotation2d(Math.PI)))
.build()));
}
}
Loading

0 comments on commit 70d5d71

Please sign in to comment.