It's too hard to tune a shooter's PID

l have been testing our shooter recently and l find that l am have huge problem in the PID tuning of our shooter. l have used P and F on my shooter and you can see the final effect below.

l know it’s far from satisfaction and the actual effect is below.


In this video, the shooter’s speed is a fixed rpm, and the ball are almost the same. But the shooting effect is totally different, l am very sure the shooter is not tuned well, but l think l can only reach this level now.

Aftering searching for some information on CD, l find that a PF may be best forme. And after seeing many team’s code, l find many of them have used supplycurrentlimit and set Status Frame period.

Will these make the motor rotates more accurately?

Besides, my purpose is to write a PID which makes me set and read the RPM from the motor. If anyone has better ideas on how to reach this, please also share it in the topic. Thanks for replying!

1 Like

Is the rpm when balls are shot and recovery behavior consistent? If so, then it might be a mechanical issue. Also, does the hood angle remain consistent after several shots?

If that’s not the case assuming the graphs shown are for the flywheel than than its oscillating quite a lot around the setpoint and could benefit from reducing P.

Also after rewatching the video has the hood PID been tuned at all? The shot arc are inconsistent which would indicate that RPM is not the cause for the shots being inconsistent

1 Like

Supply currents and status frames are for robot-level issues (brownout and CAN overuse, respectively). Not about shooting reliability.

Your graph looks (edit:okay, not great, see below) for no-load. Can you capture a graph of the balls going through the system (ie, show how much the launches disturb your setpoint)?

Posting photos of the shooter will help the non-programmers on here make suggestions about other causes.

1 Like

Are you just running the shooter motor at a set speed or are you targeting the hub? I’m no programmer, but I think that the oscillation of the hub may be an issue if you were targeting it.

The amount of oscillation I’m seeing in those graphs suggests that your feedforward is not very accurate and you’re compensating with a very high proportional gain.

Make sure you adjust the velocity measurement window settings to the minimum possible values of 1ms and 1 sample per average. Signal delay will kill your loop performance.

Make sure to go through the new WPILib flywheel tuning guide to see how the mechanism ought to respond, qualitatively, so that you have a reference to compare your actual tuning behavior to.


using just a tuned feedforward with voltage compensation should result in a very low error, P value is really to help get up to speed and back up to speed after a ball is shot. you should see almost no oscillation in your output velocity graph once tuned in.


How consistent is your shooter performance in open-loop (fixed controller output)? At the long intervals you have between shots, your shooter should recover speed even without P action. If the shots aren’t consistent in open-loop with plenty of recovery time, the shooter needs some improvement and speed control is not the solution.

You should also show controller output % on your graph. Seeing how the controller output is changing is critical to diagnosing tuning problems.


Another important item: turn off the motor brake mode! You want it set to coast down slowly!


I’m by no means an expert on this field, I barely know software, but I’ve tuned a flywheel or two. WPILib has good documentation.

Here’s what I’d recommend as a process:

  1. Make sure all of your mechanicals and sensors are as rigid and consistent as possible - good software can’t fix crap hardware.
  2. Get a fully charged battery and your best ball. Figure out what percent voltage just barely gets the ball into your goal / target / etc. Set your feed forward to this.
  3. View a graph of your error and your command voltage as you tune P. Slowly increase P until your recovery time is sufficient or until it starts to oscillate.
  4. Add D / I as needed to dampen oscillation / fix steady-state error

The idea here is that F should do almost all of the work, and all that P is doing is compensating for random friction, error, battery voltage drain (if you don’t use voltage compensation), etc. If you need more control than this, ask someone smarter than me.


I agree on adding D but adding I to a flywheel system is a bad idea. It can cause some unpredictable behavior, something which a flywheel should never have. P and D are consistent math, but I can stack up and cause inconsistencies–especially when you insert a ball into the system.


I would in general avoid I and D when tuning flywheels, adding D in my experience has never helped, either being too small to have any effect or hampering the flywheel’s ability to correct its velocity leading to more and worse oscillations than just running without any D term. I terms comes with the typical drawbacks while not having much of an effect when balls are in contact with the wheel, and if the steady state error is large than P and/or F needs to be tuned better.


Derivative gain is provably useless for controlling a flywheel at steady-state.

Not all operation is steady-state, and it can be useful in dynamic situations, but you need very crisp measurement or else you’ll just be responding to noise (it’s a second-order difference…). It’s tough; the WPILib tutorial I linked above recommends omitting it entirely.

A flywheel model only has one pole, so the only way to make it oscillate is to undersample the dynamics or introduce a bunch of measurement delay. Adding K_d in those situations doesn’t help. I’ll try to explain why you only need K_p (steady-state error due to feedforward modeling error notwithstanding).

PID controllers typically control voltage to a motor in FRC independent of the equations of motion of that motor. For position PID control, large values of K_p can lead to overshoot and K_d is commonly used to reduce overshoots. Let’s consider a flywheel controlled with a standard PID controller. Why wouldn’t K_d provide damping for velocity overshoots in this case?

Flywheel model derivation

Our simple motor model hooked up to a mass is

\begin{align} V &= IR + \frac{\omega}{K_v} \\ \tau &= I K_t \\ \tau &= J \frac{d\omega}{dt} \end{align}

First, we’ll solve for \frac{d\omega}{dt} in terms of V.

\begin{align} V &= IR + \frac{\omega}{K_v} \nonumber \\ V &= \left(\frac{\tau}{K_t}\right) R + \frac{\omega}{K_v} \nonumber \\ V &= \frac{\left(J \frac{d\omega}{dt}\right)}{K_t} R + \frac{\omega}{K_v} \nonumber \\ V &= \frac{J \frac{d\omega}{dt}}{K_t} R + \frac{\omega}{K_v} \nonumber \\ V - \frac{\omega}{K_v} &= \frac{J \frac{d\omega}{dt}}{K_t} R \nonumber \\ \frac{d\omega}{dt} &= \frac{K_t}{JR} \left(V - \frac{\omega}{K_v}\right) \nonumber \\ \underbrace{\frac{d\omega}{dt}}_{\dot{\mathbf{x}}} &= \underbrace{-\frac{K_t}{JRK_v}}_{\mathbf{A}} \underbrace{\omega}_{\mathbf{x}} + \underbrace{\frac{K_t}{JR}}_{\mathbf{B}} \underbrace{V}_{\mathbf{u}} \end{align}

Flywheel pole locations

Poles are the eigenvalues of the differential equation above, which in this case is just A. Poles can be real numbers or imaginary. Since this is a continuous model, the figure below shows the various impulse responses for different pole locations.

There’s one stable open-loop pole at -\frac{K_t}{JRK_v}. It’s a real number, so it’s on the real axis and doesn’t oscillate. Let’s try adding a simple P controller.

\begin{align*} \mathbf{u} &= \mathbf{K} (\mathbf{r} - \mathbf{x}) \\ V &= K_p (\omega_{goal} - \omega) \end{align*}

Closed-loop models have the form

\dot{\mathbf{x}} = (\mathbf{A} - \mathbf{B}\mathbf{K})\mathbf{x} + \mathbf{B}\mathbf{K}\mathbf{r}.

Therefore, the closed-loop poles are the eigenvalues of \mathbf{A} - \mathbf{B}\mathbf{K}.

\begin{align*} \dot{\mathbf{x}} &= (\mathbf{A} - \mathbf{B}\mathbf{K})\mathbf{x} + \mathbf{B}\mathbf{K}\mathbf{r} \\ \dot{\omega} &= \left(\left(-\frac{K_t}{JRK_v}\right) - \left(\frac{K_t}{JR}\right)(K_p)\right)\omega + \left(\frac{K_t}{JR}\right)(K_p)(\omega_{goal}) \\ \dot{\omega} &= -\left(\frac{K_t}{JRK_v} + \frac{K_t K_p}{JR}\right)\omega + \frac{K_t K_p}{JR}\omega_{goal} \end{align*}

This closed-loop flywheel model has one pole at -\left(\frac{K_t}{JRK_v} + \frac{K_t K_p}{JR}\right). It therefore only needs one P controller to place that pole anywhere on the real axis, and no value of K_p will cause it to leave the real axis.

A derivative term is unnecessary on an ideal flywheel. It may compensate for unmodeled dynamics such as accelerating projectiles slowing the flywheel down, but that effect may also increase recovery time; K_d drives the acceleration to zero in the undesired case of negative acceleration as well as well as the actually desired case of positive acceleration.

Discrete systems and sample delay

If we consider a discrete system instead of a continuous one (periodic updates), one pole can oscillate if there’s undersampling of the dynamics or sample delay (I won’t go into the discrete pole unit circle here because this post is already long). The only options in that case are to reduce K_p to slow down the response or fix the source of the sample delay.


Are you sure the hardware is consistent? The shot angle looks like it was changing. Is this a fixed hood shooter? How much are you compressing the ball?

I doubt this is a software problem.



@mendax1234 I presume this new thread is just a continuation of your previous thread but trying to get new people to answer for the same robot? Right? If so then everyone can look at the other thread and here are the photos. If not, I’m sorry for confusing people.

It appears (an assumption) that the PID controller is in the TalonFX (one or the other or both?) so I wouldn’t think there is a software problem with lag, etc. But we don’t have the code to review what the tolerances on the velocity for shooting are - what’s the minimum and maximum speed to allow the shot to release (for one or the other or both TalonFXs)? That could be a big software problem!

1 Like

When a shot is shot, how much recoil is there on the turret and hood? How much compression is being ran? How much backlash is there on the hood gears? Any one of those being wrong can cause shots to be inconsistent. If those are all good mechanically then I would check the hood PID to make sure the hood actually is and stays where it needs to be.

Its hard to capture many important details from static images.

In our 2022 competition robot we had major issues with ball PSI. Small differences would have drastic effects on our shots so even if the balls were “close” to the same PSI the shots would still be super inconsistent just because of how our shooter was built. I spent almost a solid month of build season trying to fix it in code and by the end I had a really good system forgetting the shooter’s RPM up to almost exactly where I wanted it but it still wasn’t good enough.

During the offseason, we developed a new robot with a completely new shooter with better compression, back rollers (this REALLY helped) and more “wrap” (distance where the ball is in contact with the flywheel). Almost instantly we were getting superrr consistent shots with a very sloppily tuned PID+FF loop.

The point i’m trying to get at is that this is probably a hardware issue. We were in a very similar situation with our robot and as soon as we changed our hardware to work better (backrollers, a second flywheel on the other side of the ball, and a heavier flywheel) our shots were immediately a lot more consistent.


You have two very distinctly different trajectories in the video - first two shots pretty vertical, maybe 60°, and last three closer to 45°. I’d be interested to see a video of the shooter firing. Surprising that it’s “bimodal” (two clusters of similar results).

Can you put some c-clamps on your hood adjustment mechanism to really lock it down?

The setpoint may also just be way way too high, it sounds like you’re getting slip on the ball with one or both rollers. If there are distinct warm spots on the ball when you catch it - there’s a lot of slip on the ball! If you’re only slipping one roller some of the time - that would explain having two trajectories.

With the hood locked and super low rpm setting - Start with a consistent low goal shot (lands within a ~4" circle level of consistent) then work back up the high goal. Change one thing at a time until you lose your consistency.

1 Like

l haven’t tested it and l don’t know. But one thing l am curious about is the if l set the rpm to around 1400, and l read around 2800 from the code. Does that mean my shooter’s PID is bad, or it is a mechanical issue?

l am sure our hood angle remains consistent since we use a 70:1 gear ration on our hood motor (775) and it is really hard to move unless we control it in code.

l have tuned the hood’s PID with Motion Magic and it works pretty well l think.

So, will this cause the radio’s disconnection?

Sorry, l am not at the lab now, but l will get one as soon as l return to the lab.