PID Control in FRC, Explained Simply
If your arm overshoots its target, your drivetrain drifts off a straight line, or your shooter never quite hits the right speed, PID control is usually the tool that fixes it. It sounds intimidating, but the core idea is simple: measure how far off you are, and adjust your motors to close that gap.
What PID actually means
PID is a feedback controller, which means it constantly compares where your mechanism is to where you want it to be. The difference between those two numbers is called the error. PID looks at that error and outputs a value to send to your motors. The name comes from its three terms, each of which reacts to the error in a different way.
- Proportional (P): contributes to the output in proportion to the current error. Big error, big push; small error, small push. This is the workhorse and does most of the job.
- Integral (I): adds up all the past error over time. The longer an error sticks around, the more the I term pushes to eliminate it.
- Derivative (D): reacts to how fast the error is changing. It acts like a brake, slowing the mechanism as it approaches the target so it does not blow past it.
Each term has a constant you tune, written as kP, kI, and kD. The controller multiplies each term by its constant and adds them together to get the final motor output.
How it looks in code
In WPILib you create a 'PIDController' with your three gains, then call its 'calculate' method every loop. You pass in your current measurement first and your setpoint (the target) second, for example 'pid.calculate(encoder.getDistance(), setpoint)'. The number it returns is what you send to your motor. By default the controller assumes it runs every 20 milliseconds, which matches the standard robot loop, so you just call it once per cycle. If you are new to structuring this kind of code, our programming and software guide walks through where this fits in a command-based robot.
How to tune it
Tuning means finding kP, kI, and kD values that make your mechanism fast and stable. The standard manual process is straightforward:
- Start with all three gains at zero.
- Slowly raise kP until the mechanism reaches its target. Keep increasing until it just starts to oscillate (bounce back and forth around the setpoint), then back it off slightly.
- If it still overshoots or oscillates, add a small amount of kD to dampen the motion. A well-tuned kP with a bit of kD handles the vast majority of FRC mechanisms.
- Change one value at a time and watch the result before moving on. Tuning two gains at once makes it impossible to tell what helped.
A quick symptom guide: too little kP and the mechanism is sluggish or never reaches the target; too much kP and it oscillates or overshoots; kD that is too high makes the motion jittery or slow to start.
Why most teams skip the I term
This trips up a lot of new programmers, so it is worth being clear: integral gain is generally not recommended for FRC use. Both the official WPILib documentation and REV Robotics advise against it for most mechanisms. The I term can introduce instability and a problem called integral windup, where accumulated error keeps building and causes a big delayed overshoot.
If your mechanism settles close to but not exactly on the target (steady-state error), the better fix is usually a feedforward controller rather than reaching for kI. Feedforward predicts the output your mechanism needs based on physics, instead of waiting for error to pile up. For modeling your system and getting solid starting kP and kD values automatically, the WPILib SysId tool is the recommended route and beats guessing by hand.
Start simple
Do not overthink it. Begin with P only, add D if you see overshoot, and leave I alone unless nothing else works. Most FRC mechanisms are well controlled with a tuned kP, a touch of kD, and a feedforward term.
Want the full picture on closed-loop control, command-based structure, and writing clean robot code? Head over to the LearnFRC programming and software guides.
Learn every department of FRC — free
393+ structured lessons, quizzes, and team tools. Built by an FRC student, for the community.
Browse the guides