Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
26acb0d
Questnav
blaze-developer Apr 9, 2025
e1da0b5
questnav
blaze-developer Apr 16, 2025
4c88cfd
Quest
blaze-developer May 7, 2025
798a5e6
Merge branch 'main' into questnav
blaze-developer May 7, 2025
c715fea
Spelling
blaze-developer May 28, 2025
6aed0c4
Merge branch 'main' into questnav
blaze-developer Jun 4, 2025
32bb82c
Merge branch 'main' into questnav
blaze-developer Jun 4, 2025
ad96ffd
questnav
blaze-developer Jun 4, 2025
2a981ea
questnav
blaze-developer Jun 4, 2025
f92cc1f
Clear queues
blaze-developer Jun 4, 2025
818d341
fix npe
blaze-developer Jun 20, 2025
b7ca7f3
Quest offsets and vendordep
blaze-developer Jul 2, 2025
53c27d7
use no offset and fix imports & update questnav
blaze-developer Jul 12, 2025
502f13f
changes from the mainline
sjcbulldog Sep 6, 2025
9dff854
Merge from
blaze-developer Sep 6, 2025
0e4a707
created a single path automode
sjcbulldog Jun 21, 2025
dcbf2f4
work on path following[
sjcbulldog Jul 23, 2025
9d6667b
updated on odom testing
sjcbulldog Jul 23, 2025
5490553
test work from last saturday
sjcbulldog Jul 30, 2025
b077091
test paths
sjcbulldog Jul 30, 2025
d66e1ba
Worked on tuning odometry and the curved path to be more accurate
blaze-developer Aug 2, 2025
5d58bd3
speed up path and add constraint zones
blaze-developer Aug 9, 2025
df625b5
Update
blaze-developer Aug 27, 2025
447013d
Undo
blaze-developer Aug 27, 2025
14ebf5e
Questnav Zeroing
blaze-developer Aug 27, 2025
7c70ec2
quest updates
blaze-developer Sep 6, 2025
fe6c859
Uncomment
blaze-developer Sep 6, 2025
043c9de
Fix error
blaze-developer Sep 6, 2025
e6abeb6
Merge branch 'main' into questnav
blaze-developer Sep 12, 2025
029d147
Final changes before merge
blaze-developer Sep 13, 2025
02333c9
Remove Paths
blaze-developer Sep 13, 2025
dffd3d7
undo onepath stuff
blaze-developer Sep 13, 2025
bdc02d2
Fix error
blaze-developer Sep 17, 2025
4dcff87
Fix pp config
blaze-developer Sep 17, 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
2 changes: 1 addition & 1 deletion src/main/deploy/pathplanner/paths/ThreeCoral1.path
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@
"rotation": 180.0
},
"useDefaultConstraints": false
}
}
28 changes: 18 additions & 10 deletions src/main/java/frc/robot/Robot.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import frc.robot.commands.misc.StateCmd;
import frc.robot.generated.CompTunerConstants;
import frc.robot.subsystems.drive.Drive;
import frc.robot.subsystems.vision.MotionTrackerVision;
import frc.simulator.engine.SimulationEngine;

/**
Expand All @@ -56,7 +57,7 @@ public class Robot extends LoggedRobot {
private RobotContainer robotContainer;

private boolean hasSetupAutos = false;
private AutoModeBaseCmd auto_cmd_ = null ;
private AutoModeBaseCmd appliedAuto = null ;

public Robot() throws RuntimeException {
//
Expand Down Expand Up @@ -216,21 +217,28 @@ public void disabledPeriodic() {
hasSetupAutos = true;
}



if (hasSetupAutos) {
Command cmd = robotContainer.getAutonomousCommand();
if (cmd != null) {
AutoModeBaseCmd autoCmd = (AutoModeBaseCmd) cmd;
if (autoCmd != null) {
Drive d = RobotContainer.getInstance().drivebase() ;
Pose2d autopose = autoCmd.getStartingPose() ;
if (auto_cmd_ == null || auto_cmd_ != autoCmd) {
Logger.recordOutput("automode/name", autoCmd.getName()) ;
AutoModeBaseCmd currentAuto = (AutoModeBaseCmd) cmd;
if (currentAuto != null) {
Drive drivebase = RobotContainer.getInstance().drivebase() ;
MotionTrackerVision quest = RobotContainer.getInstance().quest();
Pose2d autopose = currentAuto.getStartingPose() ;
if (appliedAuto == null || appliedAuto != currentAuto) { // Changing the Auto Mode
Logger.recordOutput("automode/name", currentAuto.getName()) ;
Logger.recordOutput("automode/pose", autopose) ;
d.setPose(autopose) ;
auto_cmd_ = autoCmd ;
Logger.recordOutput("poseinit/setting", "Robot Pose");
drivebase.setPose(autopose);
appliedAuto = currentAuto;
} else { // Initializing the Quest Repeatedly
quest.setPose(drivebase.getPose());
Logger.recordOutput("poseinit/setting", "Quest Pose");
}
}
}
}
}
}

Expand Down
73 changes: 33 additions & 40 deletions src/main/java/frc/robot/RobotContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.xerosw.util.MessageLogger;
import org.xerosw.util.MessageType;

import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.units.measure.Angle;
import edu.wpi.first.units.measure.Distance;
import edu.wpi.first.wpilibj.RobotState;
Expand Down Expand Up @@ -89,8 +90,9 @@
import frc.robot.subsystems.vision.AprilTagVision;
import frc.robot.subsystems.vision.CameraIO;
import frc.robot.subsystems.vision.CameraIOLimelight4;
import frc.robot.subsystems.vision.CameraIOPhotonSim;
import frc.robot.subsystems.vision.PoseEstimateConsumer;
import frc.robot.subsystems.vision.MotionTrackerVision;
import frc.robot.subsystems.vision.TrackerIO;
import frc.robot.subsystems.vision.TrackerIOQuest;
import frc.robot.subsystems.vision.VisionConstants;
import frc.robot.util.Mechanism3d;
import frc.robot.util.ReefUtil;
Expand Down Expand Up @@ -123,6 +125,7 @@ public static RobotContainer getInstance() {
// Subsystems
private Drive drivebase_;
private AprilTagVision vision_;
private MotionTrackerVision questnav_;
private OISubsystem oi_;
private ManipulatorSubsystem manipulator_;
private GrabberSubsystem grabber_;
Expand Down Expand Up @@ -160,19 +163,24 @@ private RobotContainer() {
if (Constants.getMode() != Mode.REPLAY) {
switch (Constants.getRobot()) {
case COMPETITION:

drivebase_ = new Drive(
new GyroIOPigeon2(CompTunerConstants.DrivetrainConstants.Pigeon2Id, CompTunerConstants.kCANBus),
ModuleIOTalonFX::new,
CompTunerConstants.FrontLeft,
CompTunerConstants.FrontRight,
CompTunerConstants.BackLeft,
CompTunerConstants.BackRight,
CompTunerConstants.kSpeedAt12Volts);

new GyroIOPigeon2(CompTunerConstants.DrivetrainConstants.Pigeon2Id, CompTunerConstants.kCANBus),
ModuleIOTalonFX::new,
CompTunerConstants.FrontLeft,
CompTunerConstants.FrontRight,
CompTunerConstants.BackLeft,
CompTunerConstants.BackRight,
CompTunerConstants.kSpeedAt12Volts
);

questnav_ = new MotionTrackerVision(new TrackerIOQuest(), drivebase_::addVisionMeasurement);

vision_ = new AprilTagVision(
drivebase_::addVisionMeasurement,
new CameraIOLimelight4(VisionConstants.frontLimelightName, drivebase_::getRotation)
);
// vision_.setTagFilterDistance(Meters.of(1.2));

try {
manipulator_ = new ManipulatorSubsystem(new ManipulatorIOHardware());
Expand Down Expand Up @@ -257,14 +265,6 @@ private RobotContainer() {
CompTunerConstants.BackRight,
CompTunerConstants.kSpeedAt12Volts);

vision_ = new AprilTagVision(
PoseEstimateConsumer.ignore(),
new CameraIOPhotonSim("Front", VisionConstants.frontTransform,
drivebase_::getPose, true),
new CameraIOPhotonSim("Back", VisionConstants.backTransform,
drivebase_::getPose, true)
);

try {
manipulator_ = new ManipulatorSubsystem(new ManipulatorIOHardware());
} catch (Exception ex) {
Expand Down Expand Up @@ -327,7 +327,7 @@ private RobotContainer() {

if (vision_ == null) {
int numCams = switch (Constants.getRobot()) {
default -> 3;
default -> 1;
};

CameraIO[] cams = new CameraIO[numCams];
Expand All @@ -339,6 +339,10 @@ private RobotContainer() {
cams);
}

if (questnav_ == null) {
questnav_ = new MotionTrackerVision(new TrackerIO() {}, drivebase_::addVisionMeasurement);
}

if (manipulator_ == null) {
manipulator_ = new ManipulatorSubsystem(new ManipulatorIO() {
});
Expand Down Expand Up @@ -369,7 +373,7 @@ private RobotContainer() {
() -> -gamepad_.getLeftY(),
() -> -gamepad_.getLeftX(),
() -> -gamepad_.getRightX()
);
);

// Shuffleboard Tabs
ShuffleboardTab autonomousTab = Shuffleboard.getTab("Autonomous");
Expand Down Expand Up @@ -416,6 +420,10 @@ public Drive drivebase() {
return drivebase_;
}

public MotionTrackerVision quest() {
return questnav_;
}

public XeroGamepad gamepad() {
return gamepad_;
}
Expand Down Expand Up @@ -456,6 +464,8 @@ public void setupAutos() {
odometryTest.addCommands(DriveCommands.initialFollowPathCommand(drivebase_, "Odom Test"));

autoChooser_.addOption("Odom Test (aka Kachow)", odometryTest);

autoChooser_.addOption("Zero Pose Reset", new AutoModeBaseCmd("Zero Pose", Pose2d.kZero));
}

private void subsystemCreateException(Exception ex) {
Expand Down Expand Up @@ -599,28 +609,11 @@ private void configureDriveBindings() {
* @return the command to run in autonomous
*/
public Command getAutonomousCommand() {
Command ret = null;

if (Robot.useXeroSimulator()) {
//
// In the Xero simulator, set the auto mode you want to run
// Note: the auto used here must match the simulation stimulus file set in the
// Robot.java file.
//

// ret = AutoCommands.oneCoralAuto(brain_, drivebase_, manipulator_, grabber_) ;
ret = AutoCommands.threeCoralSideAuto(brain_, vision_, drivebase_, manipulator_, grabber_, funnel_, true) ;
// ret = AutoCommands.oneCoralOneAlgaeAuto(brain_, drivebase_, manipulator_, grabber_) ;
// ret = AutoCommands.twoCoralCenterAuto(brain_, drivebase_, manipulator_, grabber_, funnel_, true);

// Command autoChosen = autoChooser_.get();
// ret = autoChosen != null ? autoChosen : tuningChooser_.get();

} else {
Command autoChosen = autoChooser_.get();
ret = autoChosen != null ? autoChosen : tuningChooser_.get();
return AutoCommands.threeCoralSideAuto(brain_, vision_, drivebase_, manipulator_, grabber_, funnel_, true);
}

return ret;
Command autoChosen = autoChooser_.get();
return autoChosen != null ? autoChosen : tuningChooser_.get();
}
}
7 changes: 5 additions & 2 deletions src/main/java/frc/robot/subsystems/drive/Drive.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ public void periodic() {

ChassisSpeeds spd = getChassisSpeeds() ;
Logger.recordOutput("drive/velocity", Math.hypot(spd.vxMetersPerSecond, spd.vyMetersPerSecond)) ;

Pose2d pose = getPose();
Logger.recordOutput("Odometry/Individual/X", pose.getX());
Logger.recordOutput("Odometry/Individual/Y", pose.getY());
}

/**
Expand Down Expand Up @@ -472,8 +476,7 @@ public void addVisionMeasurement(
double timestampSeconds,
Matrix<N3, N1> visionMeasurementStdDevs) {
Logger.recordOutput("Odometry/VisionMeasurement", visionRobotPoseMeters);
poseEstimator.addVisionMeasurement(
visionRobotPoseMeters, timestampSeconds, visionMeasurementStdDevs);
poseEstimator.addVisionMeasurement(visionRobotPoseMeters, timestampSeconds, visionMeasurementStdDevs);
}

/** Returns the maximum linear speed in meters per sec. */
Expand Down
Empty file modified src/main/java/frc/robot/subsystems/drive/GyroIO.java
100644 → 100755
Empty file.
3 changes: 2 additions & 1 deletion src/main/java/frc/robot/subsystems/drive/GyroIOPigeon2.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.ctre.phoenix6.BaseStatusSignal;
import com.ctre.phoenix6.CANBus;
import com.ctre.phoenix6.StatusCode;
import com.ctre.phoenix6.StatusSignal;
import com.ctre.phoenix6.configs.GyroTrimConfigs;
import com.ctre.phoenix6.configs.Pigeon2Configuration;
Expand Down Expand Up @@ -52,7 +53,7 @@ public GyroIOPigeon2(int Pigeon2Id, CANBus bus) {

@Override
public void updateInputs(GyroIOInputs inputs) {
inputs.connected = BaseStatusSignal.refreshAll(yaw).isOK() ;
inputs.connected = BaseStatusSignal.refreshAll(yaw).equals(StatusCode.OK);
inputs.yawPosition = Rotation2d.fromDegrees(yaw.getValueAsDouble());

inputs.odometryYawTimestamps =
Expand Down
Empty file.
Empty file.
100 changes: 100 additions & 0 deletions src/main/java/frc/robot/subsystems/vision/MotionTrackerVision.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@

package frc.robot.subsystems.vision;

import static edu.wpi.first.units.Units.Degrees;
import static edu.wpi.first.units.Units.Meters;

import org.littletonrobotics.junction.Logger;

import edu.wpi.first.math.Matrix;
import edu.wpi.first.math.VecBuilder;
import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.geometry.Transform2d;
import edu.wpi.first.math.numbers.N1;
import edu.wpi.first.math.numbers.N3;
import edu.wpi.first.wpilibj.Alert;
import edu.wpi.first.wpilibj.Alert.AlertType;
import edu.wpi.first.wpilibj.RobotState;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import gg.questnav.questnav.PoseFrame;

public class MotionTrackerVision extends SubsystemBase {

private static final Matrix<N3, N1> stdDevs = VecBuilder.fill(
0.01,
0.01,
0.01
);

private boolean useQuestNav = false;
private static final boolean calibration = false;
private static final boolean useQueuedFrames = true;

private static final Transform2d robotToQuest = new Transform2d(
!calibration ? Meters.of(0.199) : Meters.zero(),
!calibration ? Meters.of(0.282) : Meters.zero(),
new Rotation2d(Degrees.of(45))
);

// x: -0.216 y: -0.261

// time: 565-593
// time: 794-831
private final TrackerIO io_;
private final TrackerInputsAutoLogged inputs_;

private final Alert disconnectedAlert_ = new Alert("Motion Tracker Disconnected!", AlertType.kError);

private final Alert lowBatteryAlert_ = new Alert("Quest battery is low!", AlertType.kWarning);

private final PoseEstimateConsumer estimateConsumer_;

public MotionTrackerVision(TrackerIO io, PoseEstimateConsumer estimateConsumer) {
io_ = io;
inputs_ = new TrackerInputsAutoLogged();
estimateConsumer_ = estimateConsumer;
}

@Override
public void periodic() {
io_.updateInputs(inputs_);
Logger.processInputs("MotionTrackerVision", inputs_);

boolean disconnected = !inputs_.connected;
disconnectedAlert_.set(disconnected);

lowBatteryAlert_.set(inputs_.batteryPercent < 20);

if (
disconnected ||
!inputs_.isTracking ||
RobotState.isDisabled() ||
!useQuestNav
) return;

if (useQueuedFrames) {
for (PoseFrame frame : inputs_.unreadFrames) {
Pose2d robotPose = frame.questPose().transformBy(robotToQuest.inverse());
double timestamp = frame.dataTimestamp();
estimateConsumer_.integrate(robotPose, timestamp, stdDevs);
}
} else {
PoseFrame frame = inputs_.unreadFrames[inputs_.unreadFrames.length - 1];
estimateConsumer_.integrate(
frame.questPose().transformBy(robotToQuest.inverse()),
frame.dataTimestamp(),
stdDevs
);
}
}

public void setPose(Pose2d pose) {
io_.setPose(pose.transformBy(robotToQuest));
}

public boolean isConnected() {
return inputs_.connected;
}

}
Empty file.
23 changes: 23 additions & 0 deletions src/main/java/frc/robot/subsystems/vision/TrackerIO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package frc.robot.subsystems.vision;

import org.littletonrobotics.junction.AutoLog;

import edu.wpi.first.math.geometry.Pose2d;
import gg.questnav.questnav.PoseFrame;

public interface TrackerIO {
@AutoLog
public static class TrackerInputs {
public boolean connected = false;
public double timestamp = 0.0;
public double batteryPercent = 0.0;
public long frameCount = 0;
public boolean isTracking = false;
public long trackingLostCount = 0;

public PoseFrame[] unreadFrames = {};
}

public default void updateInputs(TrackerInputs inputs) {}
public default void setPose(Pose2d pose) {}
}
Loading