AprilTags are visual fiducial markers similar to QR codes, designed for:
Robot localization on the field
Precise pose estimation
Vision-based targeting
Multi-tag tracking
Known field layouts
AprilTags are the standard fiducial markers used in FRC, placed at known locations around the field. The AprilTag library helps detect these markers and determine the robot’s position.
Accurate pose estimation requires camera calibration parameters:
// Calibration from file or NetworkTablesdouble fx = 640.0; // Focal length X (pixels)double fy = 640.0; // Focal length Y (pixels)double cx = 320.0; // Principal point X (pixels)double cy = 240.0; // Principal point Y (pixels)// For a typical FRC camera (Microsoft LifeCam HD-3000)// Resolution: 640x480// Approximate calibration:AprilTagPoseEstimator.Config config = new AprilTagPoseEstimator.Config( 0.1524, // 6 inch tags 640.0, // fx 640.0, // fy 320.0, // cx (width/2) 240.0 // cy (height/2));
import edu.wpi.first.apriltag.AprilTagFieldLayout;import edu.wpi.first.apriltag.AprilTagFields;import edu.wpi.first.math.geometry.Pose3d;// Load current year's field layoutAprilTagFieldLayout fieldLayout = AprilTagFieldLayout.loadFromResource(AprilTagFields.k2024Crescendo.m_resourceFile);// Or load from fileAprilTagFieldLayout customLayout = new AprilTagFieldLayout("/path/to/layout.json");// Get tag pose on fieldOptional<Pose3d> tagPose = fieldLayout.getTagPose(4); // Tag ID 4if (tagPose.isPresent()) { Pose3d pose = tagPose.get(); System.out.printf("Tag 4 at (%.2f, %.2f, %.2f)%n", pose.getX(), pose.getY(), pose.getZ());}
#include <frc/apriltag/AprilTagFieldLayout.h>#include <frc/apriltag/AprilTagFields.h>// Load field layoutfrc::AprilTagFieldLayout fieldLayout = frc::LoadAprilTagLayoutField(frc::AprilTagField::k2024Crescendo);// Get tag posestd::optional<frc::Pose3d> tagPose = fieldLayout.GetTagPose(4);if (tagPose) { fmt::print("Tag 4 at ({:.2f}, {:.2f}, {:.2f})\n", tagPose->X().value(), tagPose->Y().value(), tagPose->Z().value());}
import edu.wpi.first.apriltag.AprilTag;// Create custom layoutList<AprilTag> tags = List.of( new AprilTag(1, new Pose3d(1.0, 2.0, 0.5, new Rotation3d())), new AprilTag(2, new Pose3d(3.0, 4.0, 0.5, new Rotation3d())));AprilTagFieldLayout layout = new AprilTagFieldLayout(tags, 16.54, 8.02);// Field dimensions: width=16.54m, height=8.02m
import org.opencv.core.*;import org.opencv.imgproc.Imgproc;public void drawDetection(Mat image, AprilTagDetection detection) { double[] corners = detection.getCorners(); // Draw outline for (int i = 0; i < 4; i++) { int j = (i + 1) % 4; Point p1 = new Point(corners[i*2], corners[i*2+1]); Point p2 = new Point(corners[j*2], corners[j*2+1]); Imgproc.line(image, p1, p2, new Scalar(0, 255, 0), 2); } // Draw center Point center = new Point(detection.getCenterX(), detection.getCenterY()); Imgproc.circle(image, center, 5, new Scalar(0, 0, 255), -1); // Draw ID String id = String.valueOf(detection.getId()); Imgproc.putText(image, id, center, Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(255, 0, 0), 2);}