Skip to content
2 min read
In progress

The Field Coordinate System and Odometry

How WPILib defines field position, Pose2d/Rotation2d, and how wheel encoders plus the gyro track the robot.

Lesson
29 / 51
Reward
+10XP

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

To navigate, a robot needs a shared definition of 'where' on the field. WPILib standardizes this.

The WPILib field coordinate system

WPILib uses the NWU (North-West-Up) convention. For the field, the origin is the bottom-right (rightmost) corner of the blue alliance wall as you stand at the blue alliance wall looking downfield. From that viewpoint:

  • The +X axis points away from you, down the field (toward the red alliance wall).
  • The +Y axis points to your left.
  • Positive rotation (theta) is counter-clockwise (CCW), following the right-hand rule. Facing straight downfield is Rotation2d.fromDegrees(0).

WPILib recommends the 'always blue origin' approach: keep the origin fixed at the blue-alliance corner for both alliances and account for your alliance in code, rather than moving the origin. This is the convention the major tools — the AprilTag field layout, PathPlanner, Choreo, and Glass/Field2d — follow, which is why it keeps everything consistent. (You may also see an alliance-relative-origin approach in older code, but the blue-origin convention is the modern standard.)

Pose2d and Rotation2d

A robot's position is a Pose2d: an (x, y) translation in meters plus a Rotation2d heading. Prefer Rotation2d.fromDegrees() / fromRadians() over juggling raw angles — Rotation2d stores sine/cosine and avoids wrap-around bugs.

Odometry

Odometry estimates the robot's Pose2d over time by combining:

  1. Wheel encoders — how far each wheel has rolled (and, for swerve, each module's angle).
  2. The gyro — the robot's heading.

WPILib provides DifferentialDriveOdometry, SwerveDriveOdometry, and MecanumDriveOdometry. Each loop you feed in the gyro angle and wheel measurements, and it integrates the motion into a new pose:

SwerveDriveOdometry odometry = new SwerveDriveOdometry(kinematics, gyro.getRotation2d(), modulePositions, startPose);
// periodic:
odometry.update(gyro.getRotation2d(), modulePositions);
Pose2d robotPose = odometry.getPoseMeters();

Why odometry alone is not enough

Odometry is smooth and updates fast, but it accumulates error: wheel slip, scrub, and gyro drift make the estimate wander from reality over a match. There is no absolute correction. The fix — covered in the vision module — is to periodically blend in absolute measurements from AprilTags using a pose estimator, which keeps the smoothness of odometry while pulling the estimate back to the truth.

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

Key takeaways

  • WPILib's recommended field origin is the blue-alliance bottom-left corner; +X is downfield, +Y is left, and CCW rotation is positive.
  • A Pose2d is (x, y) in meters plus a Rotation2d heading; use Rotation2d.fromDegrees to avoid wrap-around bugs.
  • Odometry fuses wheel encoders and the gyro into a pose but drifts over time, so it needs absolute correction.

Lesson quiz

Required

Answer all 3 questions correctly to complete this lesson.

01.In the WPILib field coordinate system, where is the origin and which way does +X point?

02.Using the WPILib field convention, what does a heading of 0 degrees mean, and which rotation direction is positive?

03.Why does encoder-and-gyro odometry drift over a match, and how does WPILib correct it?

Answer every question to submit.

All 51 lessons in Programming, Controls & Sensors