Running multiple PID loops on the drivetrain

Is it possible to use more than one PID controller for a subsystem like the drivetrain? Example: An encoder PID loop to drive to a distance setpoint, while a gyro PID loop keeps the robot going straight.

You could also substitute encoder with Ultrasonic sensor, etc.

If you can’t run them simultaneously, is there a way to switch between PID controllers to, say, drive forward 5 meters distance (via encoder), then turn 90 degrees (via gyro), then drive forward again, etc?

Yes. Feed the output of the PIDs into Arcade Drive. Use the output of the angle control PID as the joystick input that makes the robot turn, and use the output of the distance PID as the joystick input that makes the robot drive forward.

Nice and elegant. I like it.

Have you tried this before and can confirm that it works?

It gets a little tricky with the PIDController class, since it wants to write directly to a speed controller, which doesn’t work when you want to mix the results of multiple PID controllers and output to multiple speed controllers. What we did was create a class called DummyPIDOutput that implements PIDOutput but doesn’t output anything. We then read the DummyPIDOutput in our drive code and do the mixing there.

There’s probably an easier way, but this what worked for us. I’ve attached our DummyPIDOutput class.

DummyPIDOutput.java (786 Bytes)


DummyPIDOutput.java (786 Bytes)

The first few posts of this thread are useful.

I’ve spent alot of time looking at CD threads about using PIDController and picked up some useful tips about pid and java. Try searching and reading what others have posted.

We tried creating two PID controllers in our drive train subsystem. One uses two encoders(averaged) on the drive train and the other uses a gryo. In the PID constructors we specified a different PIDOutput class/object that did not write data to jaguars unless we set vars to allow it. See
http://code.google.com/p/frc2876/source/browse/Robot2013/src/org/usfirst/frc2876/Robot2013/subsystems/DriveTrain.java

And this is the command we use to combine the distance/turn PIDs to make robot drive in a straight line:
http://code.google.com/p/frc2876/source/browse/Robot2013/src/org/usfirst/frc2876/Robot2013/commands/DriveForwardStraight.java

We did not get a chance to finish testing this before having to bag the robot so I can’t say if it works. But based on the CD thread I found above plenty of teams are doing something like this.

If you extend PIDCommand and require() the subsystem, your PID will automatically be cancelled when another is started, allowing you to have different PID controls.

We do this and the logic is pretty simple.

motorL.set(straightControllerResult + turnControllerResult);
motorR.set(straightControllerResult - turnControllerResult);

Where straight controller and turn controller are separate PID controllers, using the drive encoders for distance and the gyro for angle respectively.

We did something similar to Joe (we don’t use the WPILib PIDController, but we have a similar modular output system in ours).


private class DTOutput implements PIDOuput {
  boolean isStraight = false;
  double t,s;
  public DTOutput(boolean isStraightController) {
    isStraight = isStraightController;
  }

  public void set(double val) {
    if (isStraight)
      s = val;
    else
      t = val;
    drive(t+s,t-s);
  }
 ...
  straightController = new PIDController(whatever, new DTOutput(true));
..

Inelegant that we need to cache the values, but it gets the job done.