Feedback control waits for a mistake, then reacts. Feedforward control studies the mechanism, predicts the push it will need, and applies it before any mistake exists. This is the story of how flywheels, arms, and elevators get controlled by prediction.
Two riders hit the same hill at the same speed. The orange rider waits to feel the bike slow down, then pushes harder — reacting to the error. The green rider sees the hill coming, knows what it costs, and pushes at the moment the slope starts — predicting. Watch who wins:
That's the whole idea. Feedback control measures the error — the gap between what you want and what you have — and reacts. Self-correcting, but it must be wrong before it acts. Feedforward control predicts the required effort from knowledge of the system and applies it up front. Never late — but only as good as its knowledge.
Robots are full of predictable effort: a shooter flywheel droops every shot, an arm sags under gravity, an elevator drifts down while "holding." None of that should wait to be discovered by failing first.
The orange rider is a real controller: a feedback loop. Here it is drawn in standard block-diagram notation — if boxes-and-arrows are new to you, take ten minutes with the companion primer, Boxes, Arrows, Circles, first. Read the shape: the output loops back through a sensor, gets subtracted from the setpoint, and only the leftover error is allowed to drive the motor:
Now watch the lag become a number. The widget below is this exact diagram, live — real values riding the wires of a simulated shooter flywheel:
Here's the escape from that trap. The voltage that holds a flywheel at 400 rad/s doesn't depend on any error — it depends on physics: bearing friction, how hard the motor fights back at speed. Those don't change moment to moment, so why rediscover them through error every loop? Measure them once, write them into a model, and compute the voltage directly from the setpoint.
That's feedforward. Feedback asks "how wrong am I?" — feedforward asks "knowing this mechanism, what input produces the output I want?" It's a prediction, and predictions demand a model. Getting the model is called characterization — the price of admission, paid in Part 5. In the diagram, feedforward is literally a path fed forward from the setpoint, never touching the error loop:
V — total voltage sent to the motorVff — the feedforward term: the model's prediction of what the setpoint requires, computed with no knowledge of the errorVfb — the feedback term: a correction proportional to the errorpredict(r) — the model function we build in Part 4kP — the proportional gain, volts per unit of errorr — the setpointω — the measured output.Division of labor: feedforward carries the predictable ~95% of the effort; feedback mops up model imperfection, disturbances, and battery sag. With feedforward doing the lifting, the error stays tiny — so feedback can stay gentle.
So what does predict(r) actually look like? For nearly everything on a robot, it starts from the permanent-magnet DC motor, which charges three costs, paid in voltage:
Friction charges a cover fee — below some voltage nothing moves at all. That threshold is kS, paid in whichever direction you're going. Speed charges a tax — a spinning motor is also a generator, pushing back a voltage proportional to speed (back-EMF); out-paying it costs kV volts per unit of velocity. Acceleration charges a price — fighting inertia costs kA volts per unit of acceleration. Stack them and you have WPILib's SimpleMotorFeedforward — the model for flywheels, shooters, and drivetrains:
V — the predicted voltagev — the desired velocity (the setpoint, not the measurement — this is a prediction!)a — the desired accelerationsgn(v) — the sign function: +1 moving forward, −1 in reverse; friction always opposes motion, so kS flips with directionkS — static friction voltage (volts)kV — velocity gain (volts per unit velocity), the back-EMF tax ratekA — acceleration gain (volts per unit acceleration).Cruising at constant speed? Then a = 0 and the last term vanishes — which is why kA can often be omitted for low-inertia mechanisms.
Elevators and arms are the same motor with one new bill: gravity, handled by a kG term. Watch where the geometry shows up in the math. An elevator hauls straight up — gravity pulls the same at every height, so kG is a constant:
kG — the gravity voltage: the constant voltage that exactly holds the carriage against gravity, identical at every heightv, a — desired vertical velocity and accelerationeverything else as in the flywheel equation.Set v = 0 and a = 0: the prediction is V = kG. An elevator "holding still" is not off — it's quietly paying the gravity bill forever. Note kG has no sgn(): gravity always pulls the same way, whether you're moving up or down.
An arm swings mass on a stick, so gravity's leverage changes with angle — brutal horizontal, zero straight up or down. The cosine captures exactly that:
θ — the arm angle, measured with 0° = horizontal (that convention is what makes cosine the right shape)cos(θ) — gravity's leverage: 1 at horizontal, 0 straight up or downkG — the gravity voltage at the worst case, horizontalω, α — desired angular velocity and accelerationkS, kV, kA — as before, now in angular units.This term is why an unpowered arm doesn't sag equally everywhere — and why a good arm controller applies kG·cos(θ) continuously, even when "holding still."
Play with both gravity terms below — this is the part of the model you can feel.
These three models are implemented in WPILib as the classes SimpleMotorFeedforward, ElevatorFeedforward, and ArmFeedforward — you hand them your constants and a setpoint, they hand back the predicted voltage. The derivations live in Introduction to DC Motor Feedforward, and the code-side usage in Feedforward Control in WPILib.
The equations are useless as written — full of unknowns. What is kS for your flywheel, with your bearings and your belt tension? No datasheet knows. The constants must be measured from the real mechanism: that's characterization (formally, system identification). The core trick is one line — at steady state, a = 0 and the kA term vanishes:
V — the voltage you appliedv — the steady velocity the mechanism settled atkS — the y-intercept of this linekV — its slope.This is y = b + m·x wearing a lab coat. Feed the mechanism a series of voltages, record the steady speed each produces, and the data points fall on a line. Fit the line, read off the intercept and slope, and you've characterized kS and kV.
Run that experiment yourself. The widget below has a mystery flywheel — its true constants are hidden. Collect data, fit the line, and steal its secrets.
On a real robot, WPILib automates this with the SysId tool and the SysIdRoutine class: a quasistatic test ramps voltage so slowly that acceleration stays negligible (isolating kS and kV, like our widget), and a dynamic test steps it hard to expose kA. The robot logs voltage, position, and velocity; SysId runs the regression and hands you the constants plus diagnostic plots. Setup lives in the Introduction to System Identification.
Time to run the complete two-path diagram from Part 3 on a shooter flywheel — the classic case, because a shooter lives or dies by recovery time: every ball fired rips energy out of the wheel, and the next shot is only accurate once the speed is back. Toggle each path on and off and watch what each one is actually good at. The model-error slider corrupts the feedforward's constants, simulating a sloppy characterization — the exact situation where feedback earns its keep.
1. Feedback is reaction. It's self-correcting but must be wrong before it acts — pure proportional feedback even needs a standing error to hold a standing output.
2. Feedforward is prediction. It computes the required input directly from the desired output, using a model — so it acts before any error exists.
3. The diagram tells the story. Feedforward is literally the path that runs forward from the setpoint instead of back from the error — one glance at the two-path diagram and the whole architecture is visible. (Rusty on the notation? Revisit Boxes, Arrows, Circles.)
4. Prediction is purchased with understanding. The model's constants — kS, kV, kA, kG — must be measured from the real mechanism. That's characterization, and WPILib's SysId turns it into a routine.
5. Use both. Feedforward carries the predictable bulk of the effort; feedback cleans up disturbances and model error. Big steady V_ff, small twitchy V_fb — that's the signature of a well-tuned mechanism.
plant — the mechanismsetpoint r — the goalerror e — r − outputkS — static friction (V)kV — V per velocitykA — V per accelerationkG — gravity voltage (constant for elevators, ×cos θ for arms)V = Vff + Vfb — prediction plus correction