PID Controllers

What are PIDS?

PID Controllers (short for Proportional–integral–derivative controllers) are feedback loops commonly used with machinery that require constant adjusting to their movement. For example: look at the Romi from earlier.

When you stop the Romi's movement through a trigger, the robot doesn't stop smoothly— it ends up jerking forward before stopping. This might not seem like a problem, but with much, much more powerful and expensive motors, this could end up breaking something. To combat this, we can use PID Controllers.

Error

The error is equal to the difference between the PID controller's target position, and the current position. Basically- it's measuring how far the controller itself is from its target. This value is used by the parameters below:

Parameters

Proportional Control (P)

The "P" value determines how strongly your PID controller reacts to error. This value is multiplied by the error mentioned above. The greater your KP value is, the stronger the controller reacts when the error is bigger. The P value is added onto the controller's position, bringing it closer to its target.

The kP value is determined by the user, often given as a parameter. It determines the magnitude of the controller's reaction.

The P value is equal to: P = error * kP

Theoretically, the P value is all you'll need. The problem is- you're using it to control a moving object. When your P value is equal to zero, your object still has its velocity

Integral Control (I)

This parameter adds extra acceleration for the P value. It's primarily used to counter other factors, such as gravity.

Due to this pretty niche use case, we usually set the kI value to 0, as it might cause inaccuracy.

Derivative Control (D)

The "D" value adds some de-acceleration to the P value, depending on how far the PID controller's position is from its target. It smoothens it out, so the PID controller won't overshoot as heavily once it reaches its target.

Here is a video that summarizes how the parameters work in the PID controller.


Using PID Controllers

Creating PIDController Objects

The parameters of a PID Controller are:

PIDController controller = new PIDController(double kP, double kI, double kD);

All the parameters here are used to modify the values I mentioned above. The graph below is the ideal way a PID should move the robot, but the dark magic behind PID controllers often makes their actual movement not the case. Most of the time, as mentioned in the video, the P value will end up oscillating around the target, which could end up causing issues. This is why you need to tune the D value as well.

Drawing

Now, let's talk about important values that the PID controller uses.

Tuning a PIDController Object

PIDs have different parameter values for everything, because of this, there is a process called tuning a PID. To do this you have to continuously test the motor with different parameters until one of the parameter sets creates accurate results. For our purposes, we will change the moveRobotAtDistance() function to learn tuning,

Conditions:

Here is the answer code (don't worry about the PIDController object parameters for now).

Answer code
public void goDistance(double distance){
    double pid.caluclate(m_rightEncoder.getDistance(), distance);
    go(speed,speed);
    System.out.println(m_rightEncoder.getDistance());
}

Now, if you haven't already, fill in the parameters of Ki only in the PIDController and call that method into the autonomous period autonomousPeriodic() method in the Robot class and run the program with the distance being 12 (inches). You should notice the robot, not going even close to the right distance. Now tune the kP value until it is about 0.001 inches away from 12 (inches) and not oscillating. Here are some tips for tuning the PID's kP component.

  • If the distance is undershot, increase the kP

  • If the distance is overshot, decrease the kP

  • The kP values should be small (probably less than 1)

  • Use the distances printed out to the console

After you get a good distance. I would suggest trying to make the accuracy even better using the kD component.

To use a PID, you have to use the pid.calculate() method. This method has 2 parameters, the current point, and the desired point. You can get the current point from Encoder objects. This method returns a double that will be used as a speed value that can be set to Spark motors. This is an example with our PIDController object being named pid and our Encoder object being named encoder:

// will precisely move the robot 12 units using PID
double speed = pid.calculate(encoder.getDistance(), 12)

Due to the PIDController object using encoder values, remember to reset your encoder values often to avoid problems


Last updated