Feedforward and Motion Profiling
Add feedforward to predict required output, and use trapezoid motion profiles for smooth, fast moves.
Sign in to track progress, earn XP, and save lessons.
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 single-argument calculate(velocity) overload is deprecated in favor of calculateWithVelocities(currentVel, nextVel), which discretizes correctly; the single-arg form still works 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.
Go deeper
Lesson quiz
RequiredAnswer all 3 questions correctly to complete this lesson.
1.In WPILib's SimpleMotorFeedforward, what does the kV gain represent?
2.How does feedforward control fundamentally differ from PID feedback control?
3.What does WPILib's TrapezoidProfile / motion profiling provide when combined with a ProfiledPIDController?
Answer every question to submit.