Vision is one of, if not the most versatile tool for FRC Programming. Vision can be used for:
Pose Estimation (Finding where the robot is)
Object Detection
Seeing Obstructed Field Areas
Quick Vocab:
AprilTag: The QR code looking thing on the field. Each one is assigned an ID, and the robot can use its location relative to them to find its location on the field
Pose: Position and orientation
Coprocessor: The processor other than the Rio/Systemcore set aside to process vision
Translation: Shift on a coordinate plane
Radians: Unit for angles. Degrees but better
Pose Estimation:
Most common vision application
Object Detection:
Extremely useful in pick and place games when game pieces are on the ground
Color cameras required
How to Code a basic PhotonVision Subsystem
First you are going to need to set up the cameras, field layout, etc.
To do that, you need a PhotonCamera and a PhotonPoseEstimator.
The April tag layout is currently the welded type in Peachtree. The name of the camera MUST BE THE EXACT SAME name as the one in PhotonClient (photonvision.local:5800). The robotToCamera is the 3d transform from the origin of the robot to the lens of the camera.
You are then going to call camera.getAllUnreadResults() ONLY ONCE PER LOOP and iterate through each result, estimating the robot pose from each result.
estimateCoprocMultiTagPose(result) uses multiple tags to get a more accurate pose, there are more estimation methods, but this is the most accurate and recommended. If that doesn't work (estimate.isEmpty()) you need a fallback, which right now we use the closest to reference pose method (chooses the estimate closest to the robot's current pose) another popular fallback is lowest ambiguity.
Next, you need to decide whether to reject or accept the estimated pose. In this example, maxAmbiguity is 0.3 maxSingleTagDistanceMeters is 3.8, and maxZError is 0.75.
Note: Field boundaries will be different 2027 onwards since the origin will be moved to the center of the field.
Now that you have all the poses you want to accept, you need to determine how accurate/trustworthy each one is. We do this using average distance squared divided by the number of tags seen. There is also a constant factor that each camera has that can increase/decrease standard deviations.
The higher your standard deviation, the less it will affect the pose when you fuse it with the pose.
To fuse the vision pose with the robot pose, use addVisionMeasurement() from the CTRE generated swerve drive.
For more complex logging, using a consumer, and quality of life things, see src\main\java\frc\robot\subsystems\vision\apriltag in our 2026 code.