PID Deep Dive Lesson

PID Deep Dive: Precision Control

A PID Controller is a powerful feedback control loop that is the gold standard for getting a mechanism to a specific setpoint (like an angle or position) quickly, accurately, and without wobbling or overshooting.

The Problem: Why Simple Control Fails

Imagine programming a robot arm to move to a 90-degree angle. If you simply run the motor at full power until it reaches the target, momentum will cause it to drastically overshoot. A PID controller solves this by intelligently adjusting the motor's power based on its error.

The Three Components of PID

A PID controller calculates an output (like motor speed) by combining three distinct terms. Tuning the constants (gains) for each of these terms is the key to achieving perfect control.

P - The Proportional Term (The Present)

This is the main driving force. It looks at the current error (the difference between the target and current position) and generates an output proportional to that error. The farther away you are, the more power it applies.

I - The Integral Term (The Past)

This term eliminates small, steady-state errors (like "droop" caused by friction). It looks at the accumulation of past errors over time. If the mechanism is consistently just short of its target, this term will slowly build up, adding the extra power needed to close the final gap.

D - The Derivative Term (The Future)

This is the "brake." It looks at the rate of change of the error to predict where the system is going. As the mechanism approaches its target at high speed, this term applies a counter-force to slow it down, preventing overshoot and oscillation.

PID in WPILib

We use WPILib's highly optimized `PIDController` class to handle this math for us. Our job is to provide the three tuning constants (gains): `kP`, `kI`, and `kD`.

// In an ArmSubsystem...
public class ArmSubsystem extends SubsystemBase {
    // Tuning constants - these are found through testing!
    private static final double kP = 0.05;
    private static final double kI = 0.0;
    private static final double kD = 0.01;

    private final PIDController m_pidController = new PIDController(kP, kI, kD);
    
    // ... motor and encoder objects ...

    public void setTargetAngle(double targetAngle) {
        m_pidController.setSetpoint(targetAngle);
    }
    
    @Override
    public void periodic() {
        // This is the feedback loop, running 50 times per second.
        double currentAngle = m_encoder.getDistance();
        double pidOutput = m_pidController.calculate(currentAngle);
        m_motor.set(pidOutput);
    }
}
    

Test Your Knowledge

Question: Your robot's arm moves quickly toward its target but consistently overshoots and oscillates. Which PID term is primarily responsible for dampening this oscillation and acting as a "brake"?