Feedforward: predict, don't just react
Where PID reacts to error, feedforward predicts the output a mechanism needs to follow a desired motion — before any error appears. Combining feedforward (the bulk of the output) with PID (small corrections) gives the best of both: responsive and accurate.
WPILib provides feedforward classes:
SimpleMotorFeedforward— for flywheels and drivetrains (no gravity load):SimpleMotorFeedforward ff = new SimpleMotorFeedforward(kS, kV, kA); double volts = ff.calculate(targetVelocity); motor.setVoltage(volts);ArmFeedforward— adds akG(gravity) term that depends on arm angle.ElevatorFeedforward— adds a constantkGto fight gravity on an elevator.
The gains mean:
- kS — voltage to overcome static friction.
- kV — voltage per unit of velocity (the big one).
- kA — voltage per unit of acceleration.
- kG — voltage to hold against gravity (arm/elevator only).
You find these with the SysId characterization tool. (API note: as of WPILib 2025 the two-argument calculate(velocity, acceleration) overload is deprecated in favor of calculateWithVelocities(currentVel, nextVel), which discretizes correctly; the single-argument calculate(velocity) form is not deprecated and is fine for learning.)
Combining feedforward and PID
The combination is simply adding their outputs:
double output = ff.calculate(targetVel) + pid.calculate(measuredVel, targetVel);
motor.setVoltage(output);
Feedforward does most of the work; PID cleans up the rest.
Motion profiling: smooth setpoints
Feeding a mechanism a giant instant jump ("go from 0 to 90 degrees NOW") causes a violent move. A motion profile generates a smooth path of intermediate setpoints over time. WPILib's TrapezoidProfile ramps velocity up, cruises, then ramps down — a trapezoid shape — bounded by max velocity and max acceleration constraints.
ProfiledPIDController: the convenient combo
Combining a profile with PID is so common that WPILib bundles them into ProfiledPIDController: it internally generates trapezoid setpoints and runs PID to follow them.
ProfiledPIDController controller = new ProfiledPIDController(
kP, kI, kD,
new TrapezoidProfile.Constraints(maxVel, maxAccel));
double output = controller.calculate(encoder.getPosition(), goalPosition)
+ feedforward.calculate(controller.getSetpoint().velocity);
motor.setVoltage(output);
This is the gold-standard pattern for an arm or elevator: a profile for smoothness, feedforward for prediction, PID for accuracy.
Why this matters for competition
Well-tuned feedforward + motion profiling makes mechanisms fast and repeatable — an arm that snaps to scoring position without overshoot, a flywheel that holds RPM through a shot. The difference between "it kind of works" and "it works every time" is usually here. The same profiling idea scales up to whole-robot paths, which is the next module.
Key takeaways
- Feedforward predicts required output; PID corrects the remainder. Add their outputs.
- Use SimpleMotorFeedforward (flywheel/drive), ArmFeedforward, or ElevatorFeedforward (adds kG).
- Find kS/kV/kA/kG with the SysId characterization tool.
- TrapezoidProfile generates smooth velocity-limited setpoints.
- ProfiledPIDController bundles profile + PID — the standard pattern for arms and elevators.
Keep going
Take the quiz · +10 XP with an accountMore in Motors, Sensors, and Closed-Loop Control
Sources & corrections
This lesson is AI-assisted: drafted from primary sources, then reviewed and edited by hand. Errors still get through. When one is reported we fix it and write down what changed — publicly, in the corrections log.
Sources and further reading
- Feedforward Control in WPILibdocs.wpilib.org
- Combining Feedforward and PID Controldocs.wpilib.org
- Combining Motion Profiling and PID (ProfiledPIDController)docs.wpilib.org
Read next
Articles on this, for competition day
The lesson covers how it works. These cover what to do when it breaks.
Lesson quiz
RequiredAll 3 right completes the lesson. Miss one and only that question comes back — anything you already answered correctly stays banked.
0 of 3 answered
01.In WPILib's SimpleMotorFeedforward, what does the kV gain represent?
02.How does feedforward control fundamentally differ from PID feedback control?
03.What does WPILib's TrapezoidProfile / motion profiling provide inside a ProfiledPIDController?
Answer every question to submit.
All 51 lessons in Programming, Controls & Sensors
- Not started:Mini-Project: A Closed-Loop Elevator with Motion Magic
- Not started:Mini-Project: A Velocity-Controlled Shooter on REVLib
- Not started:Mini-Project: A Teleop Swerve Drive Subsystem
- Not started:Mini-Project: An Autonomous Routine with PathPlanner
- Not started:Mini-Project: Vision-Aligned Scoring with Limelight
- Not started:State-Space Control and Kalman Filtering
- Not started:Log Replay Architecture with AdvantageKit
- Not started:Advanced Pose Estimation: Multi-Tag Fusion and Standard Deviations
- Not started:Robot Coordination, Alerts, and Operator Feedback
- Not started:Case Study: Hardening Software Before an Event