# How to use WPILIB's simplefeedforward to calculate a rpm value?

l have a shooter powered by two falcon and l try to use kP + kF to make it drive at a desired rpm. However, l find that no matter how l tune the falcon’s kP and kF, the shooter still has a tolerance of 150 rpm. That’s not what l want since it may affect our shot.

l have seen many teams using a simplefeedforward to calculate the shooter’s rpm and then using a PIDController with only a P value to optimize and they say it works well. So, l am wondering how to use a simplefeedforward to calculate a shooter’s rpm? If l want to decide the kS and kV manually, which value should l start from? Besides, after l use simplefeedforward and PIDController to calculate the last result. Which unit is the result? How can l set it to falcon? If anyone has any example code to share, l think it will be easier to understand?

What’s more, can l use Sysid to calculate the shooter motor’s ks,kv and ka? If so, how to use Sysid to calculate it?

Besides, what’s the difference between WPILIB’s simplefeedforward and the kF in the motor itself?

This is another part of your long threads related to PID tuning (and maybe radio disconnection). I just saw this one and it has been largely answered in your other threads. I’ll try to fill-in a little more explanation and may be somewhat redundant. With no publicly available complete code I have to do some guessing and I can’t point to exact lines of code to reference.

WPILib PID controller and the now separate but related WPILib Feed Forward calculator have little to do with the CTRE Talon PIDF controller at the detailed implementation level. (They solve the same problem with almost the same equations but are accessed very differently.)

You can communicate your velocity intentions to a Talon in one of two ways:

1. set the voltage (%VBus fraction of the battery) to what it takes to go your (approximate) velocity

2. set the velocity in PIDF velocity mode after initially setting the kP, kI, kD, kF

You communicate your intentions to WPILib by:

1. set the velocity

and then WPILib has to communicate to the Talon by:

1. set the voltage (%VBus fraction of the battery) based on your estimating what that voltage should be for the desired PID error correction PLUS (+) the WPILib feed forward (still, again YOU have to somehow relate voltage to velocity for your particular device - I’m not getting into that exact code)

The Talon PIDF only receives your desired velocity setpoint each iterative cycle (normally 0.02 seconds in Robot). The Talon computes internally the required voltage by its relationship of that setpoint through your preset kP, kI, kD, kF. (With those you relate velocity to voltage and determine the gain of your controller.)

That’s enough details except I’ll do feed forward a bit more since that goes directly to your question and apparent error in your code shown in other threads.

The WPILib feed forward calculation is a little more sophisticated than the Talon calculation. WPILib gives you 3 parameters to tune (static, dynamic, acceleration) and Talon only one (dynamic). As a practical matter we find the Talon method is adequate.

The result of the WPILib feed forward is a voltage to add to the WPILib PID controller output voltage and that total voltage goes to the Talon.

The Talon feed forward is intrinsic to its PIDF controller and is done automagically for you by multiplying your initially defined kF by your velocity setpoint that you set on each and every Robot iteration.

It is incorrect to send a WPILib feed forward to a Talon PIDF controller. The units are different and indeed the concepts are different. Specifically:

Say you want 800 RPM (actually use the correct Talon native velocity units but I’ll ignore that for simplicity).

If you used the WPILib feed forward correctly tuned, you might get back from it 0.15 (%VBus).

If you set the Talon in velocity mode you tell it 800. If you added the WPILib feed forward you’d be telling the Talon to go 800 + 0.15 = 800.15. That is not the velocity you wanted and may be the source of your error!!

Where is the Talon feed forward? The Talon already had multiplied your previously defined kF by the setpoint for you and added it to the error correction terms for you. Note that the single kF does usually work well enough over your velocity range. The exact calculation is in the CTRE documentation and has been repeated for you in your other threads.

Basically kF is %VBus/Velocity (I’m ignoring the 1023 native throttle units conversion which you must do). That ratio is amazingly constant over a wide range of velocity and deviations don’t much matter in the PID controller.

Calculate kF over your velocity range and pick the slightly smaller value so you don’t overshoot any of your setpoints. It’s trivial and NOT exacting - pick a %VBus and see what the velocity is near your shooter’s two desired RPMs. No need to use SYSID for Talon parameters.

I failed to clarify in the feed forward discussion that I am assuming you are using the two-parameter version of the Talon `set` method. My discussion isn’t exactly right if you are using the four-parameter `set` method. Yet another hazard of there being no code upon which to comment. Responders often can’t think of everything at the moment and rely on seeing the actual code in question to prompt a good, meaningful, specific response.

1 Like

Feedforward, by it’s definition, is not something that responds to changes in value. Feedforward is the minimum amount to do whatever you are doing. In a positional pid, feedforward is used to describe what the absolute minimum amount of effort you need to counter the forces stopping you from moving. For example, on a robot’s arm, feedforward would be the minimum energy you need to have the arm hold it’s position extended outwards at it’s farthest (or wherever it is acted on most by gravity) or on a drive train it’s the minimum energy needed to beat friction + gravity.

In your case, your feedforward should be the minimum amount of voltage needed to have the wheel spin at your desired rpm. It doesn’t matter how long it takes to do that (yet), it just needs to spin exactly at the rpm you want. Take note of what voltage (the percentage of power) you were using and that will be your feedforward.

If we wanted to water-down all of the important pid gains, here is what you would get:
kF = minimum effort to do something
kP = how the error (where you are) is proportioned to the setpoint (where you want to be)
kD = how aggressively you want to react (as error increases, do we want to add more oomph, less oomph, or the same amount of oomph
kI = how the time needed to react scales with how large the error is

you probably won’t end up using kI, but kP and kD are pretty important here. Your kP determines the “scale” your error increases by as it gets farther from the setpoint, and kD determines how aggressively to make that change. Lower kP will mean it’s a bit more sluggish, while a high kP causes overshooting.

Feedforward controls can definitely respond to changes in desired setpoint, they just don’t use error feedback.

That is one type of feedforward value. The amount needed to overcome static friction. (kS)

WPILIB includes a few feedforward calculators the SimpleMotorFeedForward class will calculate a base value to achieve a certain velocity based on calculated or observed system characteristics including the kS (Static feed forward) kV (Velocity feed forward) and kA (Acceleration) IT can be used in combination with a feedback controller (PID) to achieve a very accurate velocity control.

``````/**
* Calculates the feedforward from the gains and setpoints.
*
* @param velocity The velocity setpoint.
* @param acceleration The acceleration setpoint.
* @return The computed feedforward.
*/
public double calculate(double velocity, double acceleration) {
return ks * Math.signum(velocity) + kv * velocity + ka * acceleration;
}``````

More on feed forward can be found here Feedforward Control in WPILib — FIRST Robotics Competition documentation

IF you really want the in depth explanation @calcmogul has a book https://file.tavsys.net/control/controls-engineering-in-frc.pdf

1 Like

I hate to pick on a pretty good answer and I can be accused of splitting hairs but we have to be careful NOT to confuse. The following statement is also true for OP’s question and your example:

feedforward should be the MAXIMUM amount of voltage needed to have the wheel spin at your desired rpm

See what I mean? Feedforward is EXACTLY the amount needed to spin at the desired velocity. If using a PID controller the FF doesn’t have to be so exacting as error correction takes care of deviations.

BUT BUT BUT!!!
OP is using the TalonFX PIDF controller in VELOCITY mode so his units are the Talon native units for velocity and gain so voltage is not specified directly. The kP, kI, kD, kF generally need be set only once and usually are good for a range of velocities. I rewrote the equation for kF above and in the other thread and described that you measure the voltage (%VBus actually) and velocity ratio near an operating point and that’s pretty good for the whole range. kF for the Talon does not change with velocity - it’s internally multiplied by the setpoint velocity so the user doesn’t have to fuss with feedforward at all except to set kF once initially. (To keep %VBus predictable there is voltage compensation to help us otherwise it may change with battery load.)

And this is true to qualify what is meant by feedforward.

You can have, for example, anticipatory feedforward if you know where your system will be headed and want to get a jump start on getting there. Often but not necessarily the “jump start” is full ON or OFF. I could bore you with examples but (arguably) the Bang-Bang controller might be the ultimate example (if not an obvious or appropriate one) of “I’m slow so full ON” then “I’m fast so full OFF.” Even PID controllers, if outside their proportional zone, will have feedforward go to whatever max/min output the designer thought was appropriate and the error terms don’t have to be calculated.

2 Likes

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.