The problem of writing a PID Drive

As with my other posts, I want to add the caveat that there are others here who know a lot more about this than I do, so take my response with a grain of salt. However, I think it goes like this…

If your system (I think they tend to refer to it as a plant in control theory if you go looking around the Internet for research) is doing what you want it to do, then you do not need to tune the gain.

So let’s say we have a shooter wheel that for whatever magical reason goes to exactly the speed you want it whenever you want it to do that regardless of the external forces on it (projectile, friction, etc), you would not need PID. You would have a 1:1 ratio between input and desired output. I use the shooter because it may be more of a simplistic machine than a drivebase. It has one (or a handful that are all linked) motor(s), and only one output with two possible directions.

If however when you load that system (a projectile perhaps), it slows down, or it takes a long time to get up to speed and/ or then overshoots its target, you may want to investigate PID and Feed-Forward.

With a drivetrain, I am assuming there are always forces that will impede its perfection (friction, wheel-slip, battery voltage drop, etc.). So maybe we want to investigate some PID if we care about exactly how fast, what direction, and/ or how far it is going.

I think I am less clear on feed-forward, but since it is not linear, it may have a greater positive effect on a non-linear system (like a drivetrain) versus a linear one.

This is all conjecture, but it is in general, my rudimentary understanding of how PID works with Feed-Forward on our robots.

Oh, one other thing, there is a difference between PIDing the entire system (robot drive base), and the piece of the system(the wheel). I think this distinction is extra important when you think of swerve (what heading and what speed do I want to move as opposed to what direction and what speed does this motor need to move to get the drivebase to the desired heading, or place on the field as quick as possible).

This is why it is cool that we can have multiple PIDs on one system.

Edit: I attempted to remove the lone F for clarity’s sake as @Oblarg pointed out. I think it creates more confusion than it solves in general.

1 Like

This depends on how powerful the motor is relative to loading. If you have a very chonky turning motor (e.g. a NEO or Falcon), probably not.

You can check if you need a feedforward by slowly ramping the voltage to one of your turning motors under load and seeing how much voltage is needed to get it to start turning (notice that this is part of the recommended characterization process). If it’s nontrivial, then a feedforward is a good idea.

A minor point, but the term “PIDF” is a bit fraught; the feedforward really has nothing to do with the PID (which is a feedback loop), and usually when people talk about a “F gain” they implicitly mean one that gets multiplied by the setpoint (which is just one particular naive feedforward implementation, which would not work for a position loop).


Thank you. That distinction has actually been quite confusing.


For our drivetrain, we don’t run PID on the Talons, we run PID using the PIDController class in WPILib. And in this case, its not a velocity control loop, its a position control loop, with the “position” being the yaw angle returned from the navX-MXP.
See here:

Look at the “teleopPID()” method, along with the “DriveSubsystem()” constructor.

Note there’s some traction control work pending in the “teleopPID()” method that I’m still working out the kinks on.

1 Like

Thanks for replying !

1 Like

Hi , there! l’ve been tuning the velocity closed loop and l have run into some problems. Below is the graph of the motor’s velocity.

Is it tuned well?

And this is my PID parameters of TalonFX, so how to do next?

  • l find some problems which may indicate that the PID parameters may not be tuned well.
    Firstly, the wheel won’t give me a great enough reverse speed when l try to use my hand to move it .
    Secondly , when l set kF to 0.1 and set other PID parameters to 0. The max speed is the same . However , when l use velocity closed loop, the speed of the wheel seems to be smaller than the situation l have just mentioned . That’s why?

Besides , l also wonder how to judge that the kF value is tuned well? It there any graph that can show it?
And , should l puy my robot on the ground or put it off the ground when l tune the PID parameters?

As long as you’re putting this much time into this, you may as well try motion magic. But first, I’d encourage you to read about motion profiling, trapezoidal motion profiling, and some theory on PID and advice for tuning it. The link has a little of all of this, so it’s a good overview.


I did not post this earlier as it is more about PID than Feedforward, but Programming Done Right is helpful.

It must be on the ground. The motor loading is crucial to the system dynamics.


FYI, FRC-PDR is no longer maintained because replaced it. Also, FRC-PDR’s tuning instructions don’t discourage Ki enough.

Here’s’s equivalent: Tuning a PID Controller — FIRST Robotics Competition documentation


Thanks, but if l want to set target velocity in motion magic , how to do it ? It seems that motion magic only supports position control.

Hello, l also have another problem . That’s when l set kF to 0.1 and set other PID parameters to 0. The max speed is the same . However , when l use velocity closed loop, the speed of the wheel seems to be smaller than the situation l have just mentioned . That’s why?

“Motion Magic in firmware >= 4.17 (Talon SRX and Victor SPX) now supports an S-Curve parameter, allowing you to create a continuous velocity profile.”

(SPARK MAX has rev::ControlType::kSmartVelocity, and with WPIlib, ProfiledPIDController can be used in this way, because you supply all of the inputs/parameters.)

Feedforward is another technique that can help, since the PID portion of the control has less to do. I really meant to highlight this more than anything.

From the original question, it’s hard to know if your symptoms are from tuning, but if you have PID with no feedforward, I would not expect forward/reverse behaviors to differ. Also, neither axis on your graph has labels or units, so it’s hard to tell if it’s tuned well or not. Your PID parameters are going to be specific to your robot so, while it’s helpful to see them, it’s hard to diagnose any problems just from these.

In the end, there’s a lot in this topic, but it’s not really that hard to wrap your head around it, and this is really what will enable you to get good performance from your robot’s control logic. The first thing to figure out is if the symptom/s you are seeing are caused from PID not being tuned as well as it might be, or from some other problem. If it is the PID tuning, this may be telling you that you should do more with feedforward or explore a more sophisticated control technique.

Thanks for replying !

However , l also have another question. That’s the full output of TalonFX

What’s the full output of TalonFX?

I’m not sure you care what this value is, as it’s computed and applied internally. It might show up in the magnitude of the PID parameters, but you’ll tune these empirically. If I were in your position, I’d probably look at the provided examples and seek to understand them. You’ll need to measure the values to use with ConfigMotionCruiseVelocity() and ConfigMotionAcceleration(). Then, you tune things in a similar way as for a regular PID controller.

It seems that l need the full output to calculate the kF.

Thanks for your advice , l am now digging in the CTRE’s docs . And l will try to use your method.

“MotionMagic/ MotionProfile / MotionProfileArc: kF is multiplied by the runtime-calculated target and added to output.”

This seems to say (I don’t know the internals of any of these motor controllers) that kF is just used to scale things in these modes. In other words, you could scale kP/kI/kD yourself (try just using non-zero kP first) and leave kF alone. Since you are setting these empirically, that’s a reasonable thing to do I think.

Does it control the motor in velocity or in position. What does the targetPos mean? l guess the it means only the position but not the velocity.

I’d recommend starting with velocity control mode and applying a feedforward kF. In this mode, “Velocity Closed Loop: kF is multiplied by target velocity and added to output”. This is different than with motion magic. I’d first find a kF that gets you to your desired velocity when you set the velocity, at several different velocities. You are trying to find a value which is fairly close. If you know the range of velocities you care about, you can focus there. This is close to what you were originally doing with PID (only), but you are trying to use feedforward to produce most of the control. Then, use PID (mostly/only P should work when F is doing most of the control).

You will probably find that this is pretty good control and can stop there. If not, then you can look into motion magic. My original post should really have been worded around feedforward instead of motion magic. I think it’s better to start there.

Thanks ,since we have been using velocity closed loop before. But the swerve doesn’t behave as we expect, because it will stop suddenly with an useless but tiny rotation. In order to let our swerve drive smoothly. We decide to try motion magic. So, l am still puzzled with the target Pos in Motion magic.