Skip to content

Convert cameras to subsystems, add vision-only pose estimate for pose-seek #117

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

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0adee43
Convert cameras to subsystems, add function to get vision-only pose e…
caparomula Mar 10, 2025
49f2c69
Merge https://github.com/TripleHelixProgramming/Reefscape into drive-…
nlaverdure Mar 15, 2025
f872d1f
Switch to field April tags
caparomula Mar 21, 2025
d5500d2
Added Aapril tag json, removed reef offset, updated climber servo con…
caparomula Mar 22, 2025
cdb9ab7
Remove reef offset todo
caparomula Mar 22, 2025
5b25bcc
morning tweaks
caparomula Mar 22, 2025
fa35e3d
Fix elevator rocket
caparomula Mar 22, 2025
32127f4
Move zorro controller command into teleop init.
caparomula Mar 22, 2025
a1f46fd
sycronized blue and red auto logic
Pez357 Mar 22, 2025
0c9c866
Merge branch 'vahay' of https://github.com/TripleHelixProgramming/Ree…
Pez357 Mar 22, 2025
631ba98
removed withtimout on elevator
Pez357 Mar 22, 2025
c690ac9
added timout to both red and blue L4autos
Pez357 Mar 22, 2025
355960b
Set default stop command for swerve in autonomous
caparomula Mar 22, 2025
356eb0e
Merge branch 'vahay' of https://github.com/TripleHelixProgramming/Ree…
caparomula Mar 22, 2025
e13eb47
Prevent elevator rocket in joystick command
caparomula Mar 22, 2025
6010fbc
made the elevator and robot move at the same time.
Pez357 Mar 22, 2025
ac1571b
Tweaked the choro by 3 inches
Pez357 Mar 22, 2025
2053a6a
Widen tolerance for pose seek display
caparomula Mar 22, 2025
28d6500
Merge branch 'vahay' of https://github.com/TripleHelixProgramming/Ree…
caparomula Mar 22, 2025
5475164
Remove init from lifter joystick command
caparomula Mar 22, 2025
d4c64c8
Tweaked the redCenterToL4G choreo
Pez357 Mar 22, 2025
e85142e
Merge branch 'vahay' of https://github.com/TripleHelixProgramming/Ree…
Pez357 Mar 22, 2025
32f42c1
Merge branch 'vahay' of https://github.com/TripleHelixProgramming/Ree…
caparomula Mar 22, 2025
76bd0c0
commented out the createjoystickcontrolcommand and tweaked choreo.
Pez357 Mar 22, 2025
474ec4b
Merge branch 'vahay' of https://github.com/TripleHelixProgramming/Ree…
caparomula Mar 22, 2025
9be8f76
Another attempt to prevent skyrocket on teleop init
caparomula Mar 23, 2025
7dbda8c
Adjusted path for 1 piece auto
Pez357 Mar 23, 2025
e86226a
Add a few metrics to smart dashboard
caparomula Mar 23, 2025
1c268cf
Slowed down the red Auto in Choero
Pez357 Mar 23, 2025
31c728a
Adjust Al;gae L3 height, comment out algae wrist set angle on grab
Pez357 Mar 23, 2025
d7e10bb
Added pure odometry tracking for comparison with vision
caparomula Mar 25, 2025
c59e605
Merge remote-tracking branch 'origin/vahay' into drive-independent-vi…
caparomula Mar 25, 2025
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
404 changes: 404 additions & 0 deletions src/main/deploy/2025-reefscape-andymark.json

Large diffs are not rendered by default.

185 changes: 94 additions & 91 deletions src/main/deploy/choreo/blueCenterToL4G.traj

Large diffs are not rendered by default.

196 changes: 105 additions & 91 deletions src/main/deploy/choreo/redCenterToL4G.traj

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions src/main/java/frc/game/Reef.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
* to a pose.
*/
public enum Reef {
// TODO remove reef ceter offset
Blue(new Pose2d(Inches.of(176.75), Inches.of(158.5 + 4.5), Rotation2d.kZero)),
Blue(new Pose2d(Inches.of(176.75), Inches.of(158.5), Rotation2d.kZero)),
Red(new Pose2d(Inches.of(514.125), Inches.of(158.5), Rotation2d.kPi));

/** The radius of the reef hexagon */
Expand Down Expand Up @@ -75,10 +74,10 @@ public int getSector(Pose2d atPose) {
var delta = centerPose.getTranslation().minus(atPose.getTranslation());
int vectorAngle = (int) delta.getAngle().getDegrees();
int rayAngle = (vectorAngle + 30 + 360 + (int) centerPose.getRotation().getDegrees()) % 360;
SmartDashboard.putNumber("Sector delta X", delta.getX());
SmartDashboard.putNumber("Sector delta Y", delta.getY());
SmartDashboard.putNumber("Sector vector delta", vectorAngle);
SmartDashboard.putNumber("Sector ray angle", rayAngle);
// SmartDashboard.putNumber("Sector delta X", delta.getX());
// SmartDashboard.putNumber("Sector delta Y", delta.getY());
// SmartDashboard.putNumber("Sector vector delta", vectorAngle);
// SmartDashboard.putNumber("Sector ray angle", rayAngle);
return rayAngle / 60;
}

Expand Down
8 changes: 2 additions & 6 deletions src/main/java/frc/robot/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import edu.wpi.first.units.measure.Distance;
import edu.wpi.first.units.measure.LinearVelocity;
import edu.wpi.first.units.measure.Time;
import edu.wpi.first.wpilibj.Filesystem;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.util.Color;
import frc.game.FeederStation;
Expand All @@ -39,9 +38,6 @@ public static final class NEOVortexConstants {
}

public static final class VisionConstants {
public static final String kAprilTagLayoutPath =
Filesystem.getDeployDirectory() + "/" + "stemgym.json";

// Define the standard deviations for the pose estimator, which determine how fast the pose
// estimate converges to the vision measurement. This should depend on the vision measurement
// noise and how many or how frequently vision measurements are applied to the pose estimator.
Expand Down Expand Up @@ -228,8 +224,8 @@ public static final class RotationControllerGains {
public static final class ClimberConstants {
public static final int kClimberPort = 17;
public static final int kRatchetServoPort = 1;
public static final double kEngagedPosition = 0 / 1024.0;
public static final double kDisengedPosition = 1024.0 / 1024.0;
public static final double kEngagedPosition = 800 / 1024.0;
public static final double kDisengedPosition = 950 / 1024.0;

public static final int kCageSensorPort = 6;

Expand Down
20 changes: 5 additions & 15 deletions src/main/java/frc/robot/LEDs/LEDs.java
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,10 @@ public void displayPoseSeek(Pose2d currentPose, Pose2d targetPose) {
Segments.MIDDLE);

var x = delta.getTranslation().getMeasureX().in(Centimeters);
fill(Math.abs(x) < 3 ? Color.kWhite : x > 0 ? Color.kGreen : Color.kRed, Segments.TOP);
fill(Math.abs(x) < 5 ? Color.kWhite : x > 0 ? Color.kGreen : Color.kRed, Segments.TOP);

var y = delta.getTranslation().getMeasureY().in(Centimeters);
if (Math.abs(y) < 3) {
if (Math.abs(y) < 6) {
fill(Color.kWhite, Segments.BOTTOM);
} else {
fill(Color.kGreen, y > 0 ? Segments.leftBottom : Segments.rightBottom);
Expand Down Expand Up @@ -371,18 +371,6 @@ public Command createStandardDisplayCommand(
() -> displayDefaultInfo(isAlgeMode.getAsBoolean(), Optional.ofNullable(gamepiece.get())));
}

/**
* Create a command to display pose seeking information on the LEDs.
*
* @param targetPoseSupplier provides the target pose
* @param currentPoseSupplier provides the current pose
* @return a command to display pose seeking information
*/
public Command createPoseSeekingCommand(
Supplier<Pose2d> targetPoseSupplier, Supplier<Pose2d> currentPoseSupplier) {
return newCommand(() -> displayPoseSeek(currentPoseSupplier.get(), targetPoseSupplier.get()));
}

/**
* Create a pattern to display stacked blocks on the left and right strips.
*
Expand Down Expand Up @@ -446,8 +434,10 @@ public void displayAutoMode(
*/
auto -> {
var hasInitialPose = auto.getInitialPose().isPresent();
if (hasInitialPose) {
if (hasInitialPose && currentPose != null) {
displayPoseSeek(currentPose, auto.getInitialPose().get());
} else if (currentPose == null) {
fill(Color.kDarkGray, Segments.ALL);
}
displayAutoSelection(
auto.getAllianceColor(), auto.getOptionNumber(), agreement, hasInitialPose);
Expand Down
34 changes: 26 additions & 8 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package frc.robot;

import static edu.wpi.first.units.Units.Seconds;

import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.networktables.StructArrayPublisher;
Expand Down Expand Up @@ -115,7 +117,15 @@ public Gamepiece get() {
"Align Encoders",
new InstantCommand(() -> swerve.zeroAbsTurningEncoderOffsets()).ignoringDisable(true));

addPeriodic(() -> swerve.refreshRelativeTurningEncoder(), 0.1);
addPeriodic(() -> swerve.refreshRelativeTurningEncoder(), Seconds.of(0.1));
// TODO: see what happens with and without this odometry update
// addPeriodic(() -> updateOdometry(), Seconds.of(1));
}

public void updateOdometry() {
vision
.getEstimatedGlobalPose()
.ifPresent(pose -> swerve.resetOdometry(pose.estimatedPose.toPose2d()));
}

@Override
Expand All @@ -125,9 +135,6 @@ public void robotInit() {
DataLogManager.start();
DriverStation.startDataLog(DataLogManager.getLog());

swerve.setDefaultCommand(
new ZorroDriveCommand(swerve, DriveConstants.kDriveKinematics, driver.getHID()));

reefTargetPositionsPublisher.set(DriveConstants.kReefTargetPoses);
}

Expand Down Expand Up @@ -166,7 +173,10 @@ public void disabledInit() {
leds.replaceDefaultCommandImmediately(
leds.createAutoOptionDisplayCommand(
autoSelector,
() -> swerve.getPose(),
() ->
vision.getEstimatedGlobalPose().isPresent()
? vision.getEstimatedGlobalPose().get().estimatedPose.toPose2d()
: null,
allianceSelector.getAgreementInAllianceColor())
.ignoringDisable(true));

Expand Down Expand Up @@ -199,6 +209,7 @@ public void disabledPeriodic() {
@Override
public void autonomousInit() {
autoSelector.scheduleAuto();
swerve.setDefaultCommand(swerve.createStopCommand());
lifter.setDefaultCommand(lifter.createRemainAtCurrentHeightCommand());
leds.replaceDefaultCommandImmediately(
leds.createStandardDisplayCommand(algaeModeSupplier, gamepieceSupplier));
Expand All @@ -210,7 +221,13 @@ public void autonomousPeriodic() {}
@Override
public void teleopInit() {
autoSelector.cancelAuto();
swerve.setDefaultCommand(
new ZorroDriveCommand(swerve, DriveConstants.kDriveKinematics, driver.getHID()));

lifter.matchHeight();
lifter.resetController();
lifter.setDefaultCommand(lifter.createJoystickControlCommand(operator.getHID()));
// lifter.setDefaultCommand(lifter.createJoystickControlCommand(operator.getHID()));
leds.replaceDefaultCommandImmediately(
leds.createStandardDisplayCommand(algaeModeSupplier, gamepieceSupplier));

Expand Down Expand Up @@ -343,7 +360,7 @@ public boolean getAsBoolean() {
// Force joystick operation of the elevator
Trigger elevatorTriggerHigh = operator.axisGreaterThan(Axis.kLeftY.value, 0.9, loop).debounce(0.1);
Trigger elevatorTriggerLow = operator.axisGreaterThan(Axis.kLeftY.value, -0.9, loop).debounce(0.1);
elevatorTriggerHigh.or(elevatorTriggerLow).onTrue(lifter.createJoystickControlCommand(operator.getHID()));
// elevatorTriggerHigh.or(elevatorTriggerLow).onTrue(lifter.createJoystickControlCommand(operator.getHID()));

// Actuate climber winch
// Trigger climbTrigger = operator.axisGreaterThan(Axis.kRightY.value, -0.9, loop).debounce(0.1);
Expand Down Expand Up @@ -383,8 +400,8 @@ private void configureEventBindings() {

algaeRoller.hasAlgae
.whileTrue(algaeRoller.createHoldAlgaeCommand());
algaeRoller.hasAlgae
.onTrue(algaeWrist.createSetAngleCommand(AlgaeWristState.Barge));
// algaeRoller.hasAlgae
// .onTrue(algaeWrist.createSetAngleCommand(AlgaeWristState.Barge));
coralRoller.isRolling.or(algaeRoller.isRolling).whileTrue(createRollerAnimationCommand());
}

Expand Down Expand Up @@ -429,6 +446,7 @@ private synchronized StructPublisher<Pose2d> getPose2dPublisher(String name) {
}

protected void checkVision() {

vision
.getPoseEstimates()
.forEach(
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/frc/robot/auto/AutoMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@
import java.util.Optional;

public abstract class AutoMode {
private final Drivetrain drivetrain;
private final AutoFactory autoFactory;

public AutoMode(Drivetrain dt) {
this.drivetrain = dt;
public AutoMode(Drivetrain drivetrain) {
autoFactory =
new AutoFactory(
drivetrain::getPose,
drivetrain::setPose,
drivetrain::resetOdometry,
drivetrain::followTrajectory,
false,
drivetrain);
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/frc/robot/auto/BlueL4Auto.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ public AutoRoutine getAutoRoutine() {
blueL4AutoRoutine.active().onTrue(
Commands.parallel(
blueCenterToL4G.cmd(),
Commands.sequence(
Commands.waitSeconds(1.0),
elevator.coralL4PositionCG())));
elevator.coralL4PositionCG().withTimeout(2.0)));

blueCenterToL4G.done().onTrue(
Commands.sequence(
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/frc/robot/auto/RedL4Auto.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ public Optional<Pose2d> getInitialPose() {
public AutoRoutine getAutoRoutine() {

// spotless:off
redL4AutoRoutine.active().onTrue(redCenterToL4G.cmd());
redL4AutoRoutine.active().onTrue(
Commands.parallel(
redCenterToL4G.cmd(),
elevator.coralL4PositionCG().withTimeout(2.0)));


redCenterToL4G.done().onTrue(
Commands.sequence(
Commands.waitSeconds(0.1),
elevator.coralL4PositionCG(),
Commands.waitSeconds(0.1),
Commands.waitSeconds(0.1),
coralRoller.createOuttakeCommand().withTimeout(0.2),
Commands.waitSeconds(0.2)));

Expand Down
44 changes: 30 additions & 14 deletions src/main/java/frc/robot/drivetrain/Drivetrain.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.kinematics.ChassisSpeeds;
import edu.wpi.first.math.kinematics.SwerveDriveKinematics;
import edu.wpi.first.math.kinematics.SwerveDriveOdometry;
import edu.wpi.first.math.kinematics.SwerveModulePosition;
import edu.wpi.first.math.kinematics.SwerveModuleState;
import edu.wpi.first.math.numbers.N1;
Expand Down Expand Up @@ -47,6 +48,7 @@ public class Drivetrain extends SubsystemBase {

// The robot pose estimator for tracking swerve odometry and applying vision corrections.
private final SwerveDrivePoseEstimator poseEstimator;
private final SwerveDriveOdometry odometry;

private final PIDController xController =
new PIDController(TranslationControllerGains.kP, 0.0, 0.0);
Expand All @@ -58,8 +60,10 @@ public class Drivetrain extends SubsystemBase {
private final Canandgyro canandgyro = new Canandgyro(0);
private Rotation2d headingOffset = Rotation2d.kZero;

private StructPublisher<Pose2d> m_visionPosePublisher =
private StructPublisher<Pose2d> visionPosePublisher =
NetworkTableInstance.getDefault().getStructTopic("Vision", Pose2d.struct).publish();
private StructPublisher<Pose2d> odometryPosePublisher =
NetworkTableInstance.getDefault().getStructTopic("Odometry", Pose2d.struct).publish();

public Drivetrain(BooleanSupplier fieldRotated, Supplier<Dimensionless> elevatorHeight) {
this.fieldRotatedSupplier = fieldRotated;
Expand All @@ -81,14 +85,21 @@ public Drivetrain(BooleanSupplier fieldRotated, Supplier<Dimensionless> elevator
Pose2d.kZero,
DriveConstants.kStateStdDevs,
VisionConstants.kMultiTagStdDevs);
odometry =
new SwerveDriveOdometry(
DriveConstants.kDriveKinematics,
canandgyro.getRotation2d(),
getSwerveModulePositions());

thetaController.enableContinuousInput(-Math.PI, Math.PI);
}

@Override
public void periodic() {
poseEstimator.update(canandgyro.getRotation2d(), getSwerveModulePositions());
m_visionPosePublisher.set(poseEstimator.getEstimatedPosition());
odometry.update(canandgyro.getRotation2d(), getSwerveModulePositions());
visionPosePublisher.set(poseEstimator.getEstimatedPosition());
odometryPosePublisher.set(odometry.getPoseMeters());

for (SwerveModule module : SwerveModule.values()) {
SmartDashboard.putNumber(
Expand Down Expand Up @@ -169,8 +180,20 @@ public Pose2d getPose() {
/**
* @param pose The robot pose
*/
public void setPose(Pose2d pose) {
public void resetOdometry(Pose2d pose) {
resetOdometry(pose, false);
}

/**
* Reset the swerve drive's field pose.
*
* @param pose New robot pose.
* @param resetSimPose If the simulated robot pose should also be reset. This effectively
* teleports the robot and should only be used during the setup of the simulation world.
*/
public void resetOdometry(Pose2d pose, boolean resetSimPose) {
poseEstimator.resetPosition(canandgyro.getRotation2d(), getSwerveModulePositions(), pose);
odometry.resetPosition(canandgyro.getRotation2d(), getSwerveModulePositions(), pose);
}

public void initializeRelativeTurningEncoder() {
Expand All @@ -192,6 +215,10 @@ public void setHeadingOffset() {
fieldRotatedSupplier.getAsBoolean() ? getHeading().rotateBy(Rotation2d.kPi) : getHeading();
}

public Command createStopCommand() {
return this.run(() -> setRobotRelativeChassisSpeeds(new ChassisSpeeds()));
}

/**
* @return Array of swerve module positions
*/
Expand Down Expand Up @@ -232,17 +259,6 @@ public void addVisionMeasurement(
poseEstimator.addVisionMeasurement(visionMeasurement, timestampSeconds, stdDevs);
}

/**
* Reset the estimated pose of the swerve drive on the field.
*
* @param pose New robot pose.
* @param resetSimPose If the simulated robot pose should also be reset. This effectively
* teleports the robot and should only be used during the setup of the simulation world.
*/
public void resetPose(Pose2d pose, boolean resetSimPose) {
poseEstimator.resetPosition(canandgyro.getRotation2d(), getSwerveModulePositions(), pose);
}

public void followTrajectory(SwerveSample sample) {
Pose2d pose = getPose();

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/frc/robot/elevator/AlgaeRoller.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public AlgaeRoller() {
@Override
public void periodic() {
SmartDashboard.putNumber("Algae Roller/Velocity", encoder.getVelocity());
// SmartDashboard.putNumber("Algae Roller/Applied Duty Cycle", leaderMotor.getAppliedOutput());
// SmartDashboard.putNumber("Algae Roller/Current", leaderMotor.getOutputCurrent());
SmartDashboard.putNumber("Algae Roller/Applied Duty Cycle", leaderMotor.getAppliedOutput());
SmartDashboard.putNumber("Algae Roller/Current", leaderMotor.getOutputCurrent());
SmartDashboard.putBoolean("Algae Loaded", hasAlgae.getAsBoolean());
SmartDashboard.putBoolean("Algae isRolling", isRolling.getAsBoolean());
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/frc/robot/elevator/Elevator.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public AlgaeWrist getAlgaeWrist() {
public Command resetPositionControllers() {
return new InstantCommand(
() -> {
lifter.matchHeight();
lifter.resetController();
coralWrist.resetController();
algaeWrist.resetController();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/frc/robot/elevator/ElevatorConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public static enum LifterState {
CoralIntake(11.7),
AlgaeProcessor(12.0),
AlgaeL2(29.5),
AlgaeL3(45),
AlgaeL3(43),
AlgaeBarge(67.8),
Max(68.3);

Expand Down
Loading
Loading