VEXCode PID Tutorial

I will be allocating this thread to answering any questions in regards to the tutorial

Fair Warning: I am unsure if I have the positive and negative motor values correct, as this is all done on the top of my head. So If the robot is continuing to go even after the lateral position is reached, change

error = averagePosition - desiredValue;

to

error = desiredValue - averagePosition;

If the robot continues to go even after the turning desired is reached, change

turnError = turnDifference - desiredTurnValue;

to

turnError = desiredTurnValue - turnDifference;

Helpful information:

If you need any further clarification, respond below and I can answer :slight_smile:

Test_Project-2020-01-17T01-39-39.zip (8.0 KB)

30 Likes

Some additional information I would like to advise teams who are programming with PID:

  • I would suggest doing PD instead of PID for the drive, as the Integral loves to oscillate while the drivetrain is going, which is no bueno to the accuracy.
  • If you are applying any PID for arms or something, I would suggest having code that would set totalError to 0 once the target is officially reached. This would prevent windup.
  • I would highly suggest using External encoders instead of the integrated encoders for programming PID as it has a lot more accuracy.
8 Likes

This can be mitigated with anti-integral windup. an example of this is

if(abs(error) < integralBound){
    integral+=error*dt; 
}  else {
    integral = 0; 
}

where integralBound is a range within the error is small enough that the integral will be necessary.

Additionally, you can cap the integral to a certain value to keep it from growing out of control.

For example:

integral = abs(integral) > maxIntegral ? signum(integral) * maxIntegral : integral;

4 Likes

I never knew about that, thank you!
I know what an integral bound is, but could you elaborate on how “error > integralBound” applies? Would it require an std::abs anywhere, such as:

if(std::abs(error) > integralBound){
    integral+=error*dt; 
}  else {
    integral = 0; 
}
3 Likes

yes, you are correct. I will fix that in my example as well.

EDIT: flipped the sign, sorry. Tired rn

Looks pretty good. Well, the code does. Unless there is something about youtube quality options that I don’t know about, the only option for me was 360p. Does youtube make more options available as the video loads because I was under the impression that it presented all resolutions available? might be my end tho. Very good tutorial though.

2 Likes

I have updated the code to fit the corresponding information above:
Test_Project-2020-01-17T01-41-06.zip (8.2 KB)

Edit//: Video has been finalized and… the quality is1440p60, totally not overkill

5 Likes

Because the error is not a constant value and the target does not take a constant amount of time to reach for a given distance, it is impossible to control the integral outside of a known boundary. The integral would end up overpowering the proportional variable with the progress of time if you do not constrain it, even if you have a very low constant value. By constraining the integral to a point where the proportional value is not able to over come small external forces such as friction or physical barriers, you get much more consistent results and quicker settling times. I hope this makes sense.

6 Likes

does this work for my tray to go fast and then slow down toward the end

Yes, but there really should be no need to implement a PID loop for tilting a tray. A well-tuned P-loop should suffice when it comes to slowing down the speed of your tray as you reach your target angle.

1 Like

i have no clue what any of that means what so ever, but thanks. (i have no clue how to do pid)

I’d argue a well tuned PI loop is best for a tray because of friction and variable mass. You’re not always going to have a full loaded tray so the forces acting on the tray are not always predictable or constant. A p-loop could suffice for something like a chassis (without subsystems) if you could somehow keep the friction constant. Basically, the p term is really good at controlling momentum but the controller will not have repeatable behavior with only one term when the system is under constant, variable stress.

6 Likes

This is correct. My tray, as of now, uses a PI control loop with a weak kP, and then kI would do the rest and very slowly to settle the stack down softly.

3 Likes

Thank you so much for making this!

I have been thinking about how to implement a PID control on a dr4b lift and just would like to ask for advice on how to make this work in the user control period. One thing I have considered doing is the Slave and Master control method, and I will not reset the integral to zero once the error passes the setpoint (below).

50
(taken from George Gillard’s guide)

Also, would a PI or PD control loop be more appropriate than a full PID loop in this case?

Thanks again!

1 Like

I see the problem, since when you add weight it will continuously oscillate or fall down whenever it reaches target position. I’m not sure if this will work, but I am thinking of:

int nullifiedIntegral = 0;
while(1==1){

//kP and kD blah blah blah
 totalError = totalError + error;

if(std::abs(derivative) < 5){ //Because derivative of position is speed
nullifiedIntegral  = totalError; //This would store the integral value right before the lift goes in motion
}

if(std::abs(error) > integralBound){
    integral+=error; 
}  else {
    integral = nullifiedIntegral; 
}


}

Just my two cents on potentially overcoming this issue

1 Like

What do you want the PID for? If it’s to maintain equilibrium on the lift (maintaining both sides at an equal altitude), you could have a simple function that only executes if the lift is leaning too much to one side. Otherwise, the integrated PID is really great for maintaining motor position. You can also improve performance through hardware optimization.

2 Likes

I want to use the PID loop for maintaining equilibrium (thanks for asking).

What exactly do you mean by hardware optimisation?

In the case of maintaining equilibrium, would an Integral value actually be necessary?

That is one massive “It depends”
If you have a mere PD, it could help but not entirely, as when you add weight the robot will be less and less precise from the desired position. But other than the less precision and inaccuracies, it will work depending on what you are trying to do.

1 Like

Does this mean that in Driver control, where small changes will have to be made for one motor to maintain equilibrium, a PD loop will suffice - however in autonomous a dr4b lift may require an entire PID control loop, like the one shown in the video.