Skip to content

Pose Estimation with Limelight (MegaTag2) and PhotonVision

learnfrc.com
learnfrc.comAuthor
Veer Bajaj
Veer BajajMaintainer

Detecting a tag is one thing; getting a reliable field pose from it is another. Both ecosystems provide higher-level pose estimation.

A single AprilTag seen from far away or at an angle can be ambiguous — there are two mathematically valid orientations, and the wrong one throws your pose off badly. Limelight’s MegaTag2 (2024+) solves this by assuming you already know the robot’s heading (from your gyro) and using it to disambiguate, giving excellent single-tag results at any distance.

The workflow:

  1. Feed the gyro heading every loop: LimelightHelpers.SetRobotOrientation("limelight", yawDegrees, 0, 0, 0, 0, 0);
  2. Read the pose estimate:
LimelightHelpers.PoseEstimate mt2 =
LimelightHelpers.getBotPoseEstimate_wpiBlue_MegaTag2("limelight");

For 2024 and beyond, always use the botpose_orb_wpiblue variant (the MegaTag2 helper above) so the result is in the standard blue-origin coordinate system. Each estimate carries a timestamp and a tag count. Reject obviously bad data — for example, ignore updates when tagCount == 0 or when the robot is spinning faster than 720 deg/s (MegaTag2 relies on a trustworthy heading — Limelight’s own example rejects updates above 720 deg/s).

PhotonLib provides PhotonPoseEstimator , which combines all tags visible at one timestamp into a single field-relative pose. You construct it with the AprilTag field layout and the robot-to-camera transform. Each loop you call a strategy method — e.g. estimateCoprocMultiTagPose(result), which combines all visible tags into one solution on the coprocessor — and get an Optional<EstimatedRobotPose> containing the pose and the timestamp. (Older PhotonLib passed a PoseStrategy such as MULTI_TAG_PNP_ON_COPROCESSOR to the constructor and called a generic update(); current PhotonLib uses these per-strategy methods.)

Both tools converge on the same output your robot code wants: a Pose2d (or 3D pose), a timestamp, and a sense of confidence (more/closer tags = more trustworthy). That confidence is the bridge to the final lesson — fusing vision with odometry. Whatever tool you pick, validate it by placing the robot at a known spot on the field and confirming the reported pose matches a tape-measure check.

  • MegaTag2 uses your gyro heading to eliminate single-tag ambiguity; feed SetRobotOrientation every loop and read botpose_orb_wpiblue.
  • PhotonVision’s PhotonPoseEstimator fuses all visible tags (multi-tag PnP) into one timestamped field pose.
  • Both produce a Pose2d + timestamp + confidence, and both should be validated against a known field position.

This lesson was adapted from learnfrc.com.