Drive Straight PID's

I was just curious about how most teams tune a PID which ensures that the robot is driving straight, rather than a positional PID that aims to get the robot in its entirety to a certain position. The latter PID seems relatively straightforward to tune as the error is large in the initial position and there are noticeable changes with constants. Correct me if I’m wrong, but a straight PID generally has error at 0 and when it deviates it makes adjustments. The changes made are hard to analyze because error starts at 0. How would one go about tuning a “drive straight” PID or PD.

1 Like

Not sure if you need a full on PID for this or not, but one way you could code it would be something like this:

while(1) {

error = leftVal - rightVal;

if(error > 0) { //could also be some low bound instead of 0
  rightSidePower += powerAdjustment;
else if(error < 0) {
  leftSidePower += powerAdjustment;

you would be able to adjust the value of powerAdjustment to tune how powerfully the robot course corrects


You have to tune it by driving distances straight. I usually start with the pid gains I used for turning in place and then make them bigger as needed. (you likely want bigger gains because the error it will see will always be quite small compared to turn 90 degree pid function)


In our old code, my team had a thread called Drive::Assist that ran alongside Drive::Control and got the difference between rotations of the encoders and adjusted the output to each side of the chassis accordingly, using a seperate PD controller.


Under the tuning section in this article, there’s a few factors that you may want to consider while tuning a PID:


Using PID to drive straight is a problem that can be solved with a 2-DOF controller (two degrees of freedom). A drive train has two degrees of freedom (x and y axis) meaning you can readily control it with two PID controllers.

Think about what happens when you want the robot to turn left 90 degrees, for example. The robot has subtractive power to the left side of the chassis and additive power to the right side. As the robot approaches the target angle, less and less power is sent to either side until the final angle is achieved.

For driving to a point with PID, the robot translational speed slows down as the target is approached with less and less power being sent to the chassis.

Combining the two would look something like this: (this function sets each parameter to power either side of the chassis respectively) –– setDrive(linear speed + angular speed, linear speed - angular speed). You have one PID controller that regulates the linear speed of the robot based on the robot’s current position in relation to the target position. For this example, we’ll call the output linear speed. You have another PID controller regulating the angle of the chassis (based on how much power is sent to either side of the chassis respectively) which we’ll call angular speed. These two PID controllers respond to real-time feedback of the desired state of the robot. *Note, for a tank drive, the “front of the robot” has to be in line with the angle you want the robot to travel on Kinda hard to explain without a diagram.

This is essentially how you combine PID controllers in order to drive “straight”. The basic logic behind this is as the target angle is approached, angular speed approaches 0 and linear speed takes over the rest of the movement, otherwise angular speed adds/subtracts power from either side of the chassis until the final angle is reached. The output of either controller happens simultaneously.

A good example of how this would behave is shown with the animation here:
(I’m not entirely sure what @theol0403 used for this, but when I was testing this concept, my robot behaved precisely as this animation describes. I did not use odometry to achieve this)

Here’s some video of my implementation

Yep, that’s more or less the same conclusion I arrived to. I decided to to tune the “drive straight” PD before tuning the translation, net position based PID. I just don’t know how to really go about tuning the constants or which constant to tune first, or whether they should be tuned in conjunction or not.

You should tune each controller in isolation first and see if they synchronize well. But basically, if you want to prioritize turning more than linear power then increase the turning PID constants, otherwise decrease them. The problem with the turning PID is that it is much more likely to become unstable with higher gains because it settles while the robot is still in a dynamic state. So be aware of that.