Skip to content

Commit c148cf1

Browse files
tbowers7Team2486
andauthored
Add a pose buffer for vision measurements (#136)
* Add vision examples from good teams * WIP: Getting 254's vision code to compile * FRC254's 2024 vision code builds! -- Next step is to mesh in the parts of the vision code I need for the circular vision buffer to the base vision subsystem. * WIP: Adding SPAM's vision code * SPAM / FRC180 vision now builds -- The vision subsystem from FRC180 / SPAM now builds within the 2486 code base. Next steps are to figure out which parts of the various vision combination schemes I want to use and hack together something! * Add 6328's 2025 drive-to-pose algorithm * Make cleaner diff against Az-RBSI * Update FRC254's vision to 2025 version * Fix rebase error * Clean non-ASCII characters * Compilable Vision with pose buffering -- Create a pose buffer and use timestamps to match vision values with those from odometry to reduce jitter. Also be able to define certain tags in whose location we trust more (e.g. HUB in 2026) in the event of field misshapenness. Weave the new Vision structure together with the drivetrain to allow for timestamped pose insertion into the estimator. --------- Co-authored-by: NutHouse coco-prog-3 <github@team2486.org>
1 parent a7d8456 commit c148cf1

11 files changed

Lines changed: 939 additions & 474 deletions

src/main/java/frc/robot/Constants.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,16 @@ public static final class AutoConstants {
416416
/** Vision Constants (Assuming PhotonVision) ***************************** */
417417
public static class VisionConstants {
418418

419+
public static final java.util.Set<Integer> kTrustedTags =
420+
java.util.Set.of(2, 3, 4, 5, 8, 9, 10, 11, 18, 19, 20, 21, 24, 25, 26, 27); // HUB AprilTags
421+
422+
// Noise scaling factors (lower = more trusted)
423+
public static final double kTrustedTagStdDevScale = 0.6; // 40% more weight
424+
public static final double kUntrustedTagStdDevScale = 1.3; // 30% less weight
425+
426+
// Optional: if true, reject observations that contain no trusted tags
427+
public static final boolean kRequireTrustedTag = false;
428+
419429
// AprilTag Identification Constants
420430
public static final double kAmbiguityThreshold = 0.4;
421431
public static final double kTargetLogTimeSecs = 0.1;

src/main/java/frc/robot/Robot.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import com.revrobotics.util.StatusLogger;
2121
import edu.wpi.first.wpilibj.DriverStation;
22+
import edu.wpi.first.wpilibj.DriverStation.Alliance;
2223
import edu.wpi.first.wpilibj.Threads;
2324
import edu.wpi.first.wpilibj.Timer;
2425
import edu.wpi.first.wpilibj2.command.Command;
@@ -47,6 +48,7 @@ public class Robot extends LoggedRobot {
4748
private Command m_autoCommandPathPlanner;
4849
private RobotContainer m_robotContainer;
4950
private Timer m_disabledTimer;
51+
private static boolean isBlueAlliance = false;
5052

5153
// Define simulation fields here
5254
private VisionSystemSim visionSim;
@@ -135,9 +137,13 @@ public Robot() {
135137
/** TESTING VERSION OF ROBOTPERIODIC FOR OVERRUN SOURCES */
136138
@Override
137139
public void robotPeriodic() {
140+
141+
isBlueAlliance = DriverStation.getAlliance().orElse(Alliance.Blue) == Alliance.Blue;
142+
138143
final long t0 = System.nanoTime();
139144

140145
if (isReal()) {
146+
// Switch thread to high priority to improve loop timing
141147
Threads.setCurrentThreadPriority(true, 99);
142148
}
143149
final long t1 = System.nanoTime();
@@ -186,6 +192,7 @@ public void autonomousInit() {
186192
CommandScheduler.getInstance().cancelAll();
187193
m_robotContainer.getDrivebase().setMotorBrake(true);
188194
m_robotContainer.getDrivebase().resetHeadingController();
195+
m_robotContainer.getVision().resetPoseGate(Timer.getFPGATimestamp());
189196

190197
// TODO: Make sure Gyro inits here with whatever is in the path planning thingie
191198
switch (Constants.getAutoType()) {
@@ -315,4 +322,13 @@ public void simulationPeriodic() {
315322
// Update sim each sim tick
316323
visionSim.update(m_robotContainer.getDrivebase().getPose());
317324
}
325+
326+
// Helper method to simplify checking if the robot is blue or red alliance
327+
public static boolean isBlue() {
328+
return isBlueAlliance;
329+
}
330+
331+
public static boolean isRed() {
332+
return !isBlue();
333+
}
318334
}

src/main/java/frc/robot/RobotContainer.java

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import edu.wpi.first.wpilibj2.command.button.RobotModeTriggers;
3535
import edu.wpi.first.wpilibj2.command.sysid.SysIdRoutine;
3636
import frc.robot.Constants.CANBuses;
37-
import frc.robot.Constants.Cameras;
3837
import frc.robot.Constants.OperatorConstants;
3938
import frc.robot.FieldConstants.AprilTagLayoutType;
4039
import frc.robot.commands.AutopilotCommands;
@@ -75,6 +74,9 @@
7574
/** This is the location for defining robot hardware, commands, and controller button bindings. */
7675
public class RobotContainer {
7776

77+
private static final boolean USE_MAPLESIM = true;
78+
public static final boolean MAPLESIM = USE_MAPLESIM && Robot.isSimulation();
79+
7880
/** Define the Driver and, optionally, the Operator/Co-Driver Controllers */
7981
// Replace with ``CommandPS4Controller`` or ``CommandJoystick`` if needed
8082
final CommandXboxController driverController = new CommandXboxController(0); // Main Driver
@@ -128,36 +130,7 @@ public class RobotContainer {
128130
// Alerts
129131
private final Alert aprilTagLayoutAlert = new Alert("", AlertType.INFO);
130132

131-
// Vision Factories
132-
private VisionIO[] buildVisionIOsReal(Drive drive) {
133-
return switch (Constants.getVisionType()) {
134-
case PHOTON ->
135-
Arrays.stream(Cameras.ALL)
136-
.map(c -> (VisionIO) new VisionIOPhotonVision(c.name(), c.robotToCamera()))
137-
.toArray(VisionIO[]::new);
138-
139-
case LIMELIGHT ->
140-
Arrays.stream(Cameras.ALL)
141-
.map(c -> (VisionIO) new VisionIOLimelight(c.name(), drive::getHeading))
142-
.toArray(VisionIO[]::new);
143-
144-
case NONE -> new VisionIO[] {new VisionIO() {}};
145-
};
146-
}
147-
148-
private static VisionIO[] buildVisionIOsSim(Drive drive) {
149-
var cams = Constants.Cameras.ALL;
150-
VisionIO[] ios = new VisionIO[cams.length];
151-
for (int i = 0; i < cams.length; i++) {
152-
var cfg = cams[i];
153-
ios[i] = new VisionIOPhotonVisionSim(cfg.name(), cfg.robotToCamera(), drive::getPose);
154-
}
155-
return ios;
156-
}
157-
158-
private VisionIO[] buildVisionIOsReplay() {
159-
return new VisionIO[] {new VisionIO() {}};
160-
}
133+
public static RobotContainer instance;
161134

162135
/**
163136
* Constructor for the Robot Container. This container holds subsystems, opertator interface
@@ -179,7 +152,9 @@ public RobotContainer() {
179152

180153
m_drivebase = new Drive(m_imu);
181154
m_flywheel = new Flywheel(new FlywheelIOSim()); // new Flywheel(new FlywheelIOTalonFX());
182-
m_vision = new Vision(m_drivebase::addVisionMeasurement, buildVisionIOsReal(m_drivebase));
155+
m_vision =
156+
new Vision(
157+
m_drivebase, m_drivebase::addVisionMeasurement, buildVisionIOsReal(m_drivebase));
183158
m_accel = new Accelerometer(m_imu);
184159
sweep = null;
185160
break;
@@ -193,11 +168,9 @@ public RobotContainer() {
193168

194169
// ---------------- Vision IOs (robot code) ----------------
195170
var cams = frc.robot.Constants.Cameras.ALL;
196-
197-
// If you keep Vision expecting exactly two cameras:
198-
VisionIO[] visionIOs = buildVisionIOsSim(m_drivebase);
199-
m_vision = new Vision(m_drivebase::addVisionMeasurement, visionIOs);
200-
171+
m_vision =
172+
new Vision(
173+
m_drivebase, m_drivebase::addVisionMeasurement, buildVisionIOsSim(m_drivebase));
201174
m_accel = new Accelerometer(m_imu);
202175

203176
// ---------------- CameraSweepEvaluator (sim-only analysis) ----------------
@@ -231,7 +204,8 @@ public RobotContainer() {
231204
m_imu = new Imu(new ImuIOSim() {});
232205
m_drivebase = new Drive(m_imu);
233206
m_flywheel = new Flywheel(new FlywheelIO() {});
234-
m_vision = new Vision(m_drivebase::addVisionMeasurement, buildVisionIOsReplay());
207+
m_vision =
208+
new Vision(m_drivebase, m_drivebase::addVisionMeasurement, buildVisionIOsReplay());
235209
m_accel = new Accelerometer(m_imu);
236210
sweep = null;
237211
break;
@@ -493,6 +467,11 @@ public Drive getDrivebase() {
493467
return m_drivebase;
494468
}
495469

470+
/** Vision getter method for use with Robot.java */
471+
public Vision getVision() {
472+
return m_vision;
473+
}
474+
496475
/**
497476
* Set up the SysID routines from AdvantageKit
498477
*
@@ -536,6 +515,40 @@ private void definesysIdRoutines() {
536515
}
537516
}
538517

518+
// Vision Factories
519+
// Vision Factories (REAL)
520+
private VisionIO[] buildVisionIOsReal(Drive drive) {
521+
return switch (Constants.getVisionType()) {
522+
case PHOTON ->
523+
java.util.Arrays.stream(Constants.Cameras.ALL)
524+
.map(c -> (VisionIO) new VisionIOPhotonVision(c.name(), c.robotToCamera()))
525+
.toArray(VisionIO[]::new);
526+
527+
case LIMELIGHT ->
528+
java.util.Arrays.stream(Constants.Cameras.ALL)
529+
.map(c -> (VisionIO) new VisionIOLimelight(c.name(), drive::getHeading))
530+
.toArray(VisionIO[]::new);
531+
532+
case NONE -> new VisionIO[] {}; // recommended: no cameras
533+
};
534+
}
535+
536+
// Vision Factories (SIM)
537+
private VisionIO[] buildVisionIOsSim(Drive drive) {
538+
var cams = Constants.Cameras.ALL;
539+
VisionIO[] ios = new VisionIO[cams.length];
540+
for (int i = 0; i < cams.length; i++) {
541+
var cfg = cams[i];
542+
ios[i] = new VisionIOPhotonVisionSim(cfg.name(), cfg.robotToCamera(), drive::getPose);
543+
}
544+
return ios;
545+
}
546+
547+
// Vision Factories (REPLAY)
548+
private VisionIO[] buildVisionIOsReplay() {
549+
return new VisionIO[] {}; // simplest: Vision does nothing during replay
550+
}
551+
539552
/**
540553
* Example Choreo auto command
541554
*

0 commit comments

Comments
 (0)