Python Drivetrain PID

We’ve got one last hurdle to jump over before solidifying Python for 2018.

Our first approach was to use a left and right controller through the WPIlib PID controller object but we aren’t too sure where the PID controller gets the feedback from. We’ve got a left and right encoder set as the source but the robot veeres in one direction depending on the output range.

Our second approach was to use a controller that takes the difference between the left and right side encoder counts as the input.

We also wrote our own linearized_drive class to access multiple motors per drive side.

Simple question:

**How do we make a robot drive straight using Python’s pid?
**
It would be very helpful if someone could post more-or-less “drop-in” code so I could test it in the sim.

While it’s certainly doable to drive straight using encoders, it does beg the question, why not a gyro? The purpose of encoders is for distance, while using a gyro will pretty much do exactly what you want. However, let’s see if I can’t help with what you’re trying to do as is.


self.pid = wpilib.PIDController(???)

I don’t know how far along you are currently, so I’ll start from the beginning.

You need to create a PIDController that has your P, I and D (as expected) but we also need to give it a source and output, but what would those be?

Well, your source is going to be the ‘feedback’. This would be maybe a combined encoder class that extends PIDSource, and has a pidGet method. This should return the difference in encoder outputs, because that’s the value that you’re trying to correct. You’ll also need a drive class that has a pidWrite method. This will most likely take the argument in pidWrite, and apply that to the rotation of robotdrive.


class TwoEncoders(PIDSource):

    def pidGet(self):
        return self.right.get() - self.left.get() # I recommend right - left because in robotdrive, right is positive
class Drive(PIDOutput):
    
    def pidWrite(self, value):
        self.rotation = value

    def drive(self):
        self.robotdrive.arcadedrive(self.forward, self.rotation)

class Robot:

    self.pid = wpilib.PIDController(P, I, D, self.TwoEncoders, self.Drive)


And since your ideal drive straight is to have the difference in encoders equal 0, you should use 0 as the setpoint.

Please try this, let me know if it works (or doesn’t). If you have code that you think should work but doesn’t, send a repo or gist link and I’ll take a look.

Best,
Tim

Thanks for your assistance. Using the ideas from your post and our previous code, we were able to get our PID working. Thanks again!