Skip to content
2 min read
In progress

AprilTag Vision: Knowing Where You Are with PhotonVision

Use a coprocessor and PhotonVision to read AprilTags and fuse vision into WPILib pose estimation for field-relative positioning.

Lesson
26 / 28
Reward
+10XP

Sign in to track progress, earn XP, and save lessons.

AprilTags are the fiducial markers placed around the FRC field. By detecting them with a camera, your robot can compute its own position on the field — enabling automated alignment, reliable autos, and shot-aiming. The 2026 REBUILT field uses the 36h11 tag family (IDs 1-32), with 8.125-inch tags on the Hub, Tower Wall, Outpost, and Trenches.

The architecture. Image processing is too heavy for the roboRIO, so it runs on a coprocessor — commonly an Orange Pi or Raspberry Pi running PhotonVision — connected by Ethernet to the radio. The camera (e.g. an Arducam OV9281 global-shutter or a Limelight) feeds PhotonVision, which detects tags and publishes results over NetworkTables. Your robot code reads them with the PhotonLib vendor library.

Calibrate first — this is non-negotiable for 3D. To get a tag's 3D pose you must calibrate the camera at the resolution you will run. In PhotonVision you photograph a ChArUco/chessboard board from many angles and distances. Calibration solves for focal length, optical center, and distortion. Skipping or rushing this is a top cause of garbage pose data.

Use the right field layout. For 2026 there are two official field layouts — the welded layout (which PhotonVision ships with) and the AndyMark layout. Select the one matching the event field, both on the coprocessor and in your pose-estimation setup, or every pose will be subtly wrong (the AndyMark vs welded difference can be ~0.5 inch).

MultiTag and pose estimation. Enabling MultiTag estimation lets PhotonVision combine all visible tags using the field-layout JSON to produce one robust camera-to-field pose. In code, PhotonPoseEstimator turns pipeline results into a robot pose. The professional move is to fuse vision into a SwerveDrivePoseEstimator (or DifferentialDrivePoseEstimator) with addVisionMeasurement(). Conceptually:

// Pull unread results, run the estimator, push valid poses in.
for (var result : camera.getAllUnreadResults()) {
  Optional<EstimatedRobotPose> est = photonEstimator.update(result);
  est.ifPresent(e ->
      poseEstimator.addVisionMeasurement(
          e.estimatedPose.toPose2d(), e.timestampSeconds));
}

The exact PhotonLib API moves between seasons — recent versions deprecated getLatestResult() in favor of getAllUnreadResults() and added strategy-specific estimate methods — so check the current PhotonVision docs for your installed version. The fusion idea is stable: blend fast wheel/gyro odometry with absolute vision corrections, so odometry gives smooth high-rate position while vision periodically snaps out accumulated drift. Tune the trust (standard deviations) so noisy single-tag readings don't yank the pose around.

The REBUILT payoff: a robot that knows its field pose can auto-align to the Hub for consistent Fuel shots and run repeatable autos that don't drift over the 20-second period. Create one PhotonPoseEstimator per camera; multiple cameras give more frequent corrections and fewer blind spots.

Spot an error or something out of date?Log in to suggest an edit

Key takeaways

  • Run PhotonVision on a coprocessor (Pi/Orange Pi) reading 36h11 AprilTags; the roboRIO consumes results via PhotonLib over NetworkTables
  • Calibrate the camera at your run resolution and select the correct 2026 field layout (welded vs AndyMark) on both coprocessor and pose estimator
  • Fuse vision into a WPILib pose estimator with addVisionMeasurement(); the PhotonLib result API shifts by season (getAllUnreadResults replaced getLatestResult), so verify against your version's docs

Lesson quiz

Required

Answer all 3 questions correctly to complete this lesson.

01.What is the main advantage of PhotonVision's MultiTag localization?

02.What must be done before using 3D AprilTag tracking in PhotonVision?

03.What does PhotonPoseEstimator provide to the robot's pose estimation?

Answer every question to submit.

All 28 lessons in Getting Started with FRC